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.
Related
I am using Drracket for my project. I am using the language SICP(#lang sicp) for my project. For one of my implementations i require the use of scheme package called (require (planet dyoo/simply-scheme)). Scheme is not recognising require keyword. But if i change my language to #lang racket "require" is recognised as an keyword. My project makes use of set-car! and set-cdr! which is available in sicp language and not in racket. Is there any work around.
Below is some excerpts of my code:
#lang sicp
(require (planet dyoo/simply-scheme))
(define crosscuts 0)
and
(define (move-north steps_to_move)
(set-cdr! current_position ( + (y_coord current_position) steps_to_move)))
First of all, here are things that I want to note:
It's generally better to use #lang racket because #lang sicp is very limited. You can still access set-car! (though it's named set-mcar!). See the documentation at https://docs.racket-lang.org/reference/mpairs.html.
In case you decide to use #lang racket, do you actually need to use mutable data structure? Avoiding mutation is a defining trait of functional programming. And if you really do need mutable data structure, can you use struct with #:mutable instead? It's more Racket-y. See the documentation at https://docs.racket-lang.org/reference/define-struct.html.
This might not be possible, but generally I would avoid using Planet package. Planet is an old package system that is no longer recommended. It looks like there's no simply-scheme in the new package system, however, so you might really need to use Planet here.
If you really want to use #lang sicp, note the margin note at https://docs.racket-lang.org/sicp-manual/SICP_Language.html
R5RS has no require to avoid breaking programs that use the name require. #%require is therefore used instead.
#%require is a much more primitive operation, however. Depending on your require spec, it might or might not be easy to switch from require to #%require.
So first, try to replace require with #%require and see if it works. If it is, great, you are done.
But if it errors, then it means your require spec can't be processed by #%require. One possible solution is to use #%require to get require from Racket, so that you can use require to do more complex things.
(#%require (only racket require))
(require ....)
I wrote a program in Racket (the source code is in a .rkt file with #lang racket at the top). I also wrote a library in (mostly) portable R7RS Scheme. Can I use the library in the program in a clean way?
My goal is for the library to be widely portable between Scheme implementations (at least the R7RS-compliant ones, ideally others as well). There is a third-party R7RS shim for Racket but as far as I can tell it requires me to type #lang r7rs at the top of my source file. I presume this #lang directive would confuse Schemes other than Racket.
Can I put the core of my library in one or more portable .scm source files and then have one .rkt file with the #lang r7rs directive that tells Racket to include the portable files somehow? Does Racket understand some kind of library definition file such as the .sld used on snow-fort?
I tried to look all over the Racket documentation but I can't find this discussed anywhere. Nor did I find a general Scheme portability FAQ or best practices document.
I managed to mix Racket and R7RS code for real work and made an example of the technique on GitHub.
Here's a copy of the readme from that repo:
The Racket R7RS Shim
Racket doesn't ship with R7RS support. It's in the third-party package
r7rs by Alexis King: https://github.com/lexi-lambda/racket-r7rs
Despite not being an official part of Racket, it worked just fine for
me (I used a moderately complex library to do HTML parsing and wrote
some farily involved string processing and tree walking on top of it,
so this is definitely useful for real work).
You can install the shim via raco pkg install r7rs. Note also that
info.rkt lists r7rs in the dependencies, which you need for Heroku
and the like.
Modules
app -- a Racket application
lib -- an R7RS library used by app
sublib -- an R7RS library used by lib
What files the modules are made of
So app needs just one file, app.rkt, like any normal Racket
module.
But lib and sublib need 3 files each. lib.scm is the Scheme
code. lib.sld is the Scheme library definition. And lib.rkt is a
Racket wrapper for it. Technically you could combine lib.sld and
lib.scm into one file but it's cleaner to have them separate. You
could also copy all your Scheme code directly into lib.rkt but then
you can't import it into other Schemes.
Note that lib.scm doesn't have an (import ...) form at the top.
The imports are inside the define-library form in lib.sld. The
define-library form uses (include ...) to include the actual code
in lib.scm.
The job of lib.rkt is just to say #lang r7rs to Racket and then
include the Scheme stuff. It first needs to (import (scheme base))
so that we can use include and export. The included .sld files
import everything else from the Scheme standard that the library
needs.
Note that lib depends on sublib but sublib is not imported by
the define-library form in lib.sld. Instead, lib.rkt has to load
lib and all its dependencies: it contains (include "sublib.sld")
in addition to the obvious (include "lib.sld").
So lib.sld imports only stuff from the Scheme standard whereas
lib.rkt imports all our custom libraries. I had to resort to this
hack because I couldn't get the Racket module finder to find sublib
if I put it in the (define-library ...) imports. I didn't try hard
at all so there may well be a way to make it work.
Mutable vs immutable lists
Racket uses immutable cons cells (made by Racket's cons, satisfies
pair?) by default whereas R7RS uses mutable cons cells (made by
Racket's mcons, satisfies mpair?). That is, when you call cons
on the Scheme side, it actually makes something that looks to Racket
as if you had called mcons on the Racket side. A mutable cons means
you can use Scheme's set-car! and set-cdr! to alter it in place,
whereas the car and cdr of an immutable cons can't be changed after
the initial cons.
By default, Racket displays lists made out of mutable conses using
{curly braces} instead of (ordinary parentheses). This will bite
you when you pass lists over the R7RS--Racket boundary. You can print
using ordinary parentheses by changing the print-mpair-curly-braces
parameter but for many things it may be easier to convert your lists
(and trees) from mutable to immutable.
I don't know whether the Racket R7RS shim allows you to make immutable
conses on the Scheme side. It would be nice to have an option for
Scheme cons to make immutable conses (in that case set-car! and
set-cdr! would cause an error, which is fine for code using only
immutable data structures).
Where to find R7RS libraries
Lots of R7RS libraries are collected by Alex Shinn at
http://snow-fort.org/
Bottom line
The upshot of all this is that you can mix R7RS and Racket with a
little work and your codebase stays pretty clean (at least for simple
cases).
I have been curious lately about DSLs, specifically, how to implement them in Lisp,
since it looks like a piece of cake compare to the alternatives.
Looking for information I cannot find any evidence of a non-lisp DSEL in Lisp in internet.
So my question is:
Is it possible to implement a DSL with non-lisp syntax in lisp with the use of macros?
How is this achieved?
Can the reader of lisp be replaced by a custom reader that translates code to lisp structure?
If the former is true: is this a common way to implement "non-lispy" DSELs?
Short version: Racket does this.
In more detail: Racket, a descendant of Scheme, has a really well-thought-out story here. A Racket module/file can begin with a language declaration, e.g.
#lang algol60
... and then the rest of the file can be written in the given language. (Yes, algol60 is built in.)
In order to develop your own language, you need to write a package that is a language specification, that shows how to expand the syntax of this language into the syntax of the underlying language (in this case, Racket). Anyone can write such packages, and then distribute them to allow others to write programs in this language. There are examples of such language specifications included with Racket, e.g. the algol 60 example mentioned earlier.
I think this is exactly what you're asking for?
ObDisclaimer: Yes, I am a Racket developer.
How do you implement the surface language of a programming language? You write a parser or use a parser generator. You can do that in Lisp, too.
There are many examples of general purpose and domain specific languages written in Lisp - not using s-expression syntax.
Historically the first ML (an extension language for a theorem prover) was written in Lisp. Macsyma (a language for computer algebra) is written in Lisp. In many cases there is some kind of 'end user', for which a non-s-expression language needs to be written/supported. Sometimes there are languages which exist and need to be supported.
Using macros and read macros you can implement some languages or extend the Lisp language. For example it is easy to add JSON syntax to Lisp using a read macro. Also some kind of infix syntax. XML (example: XMLisp).
There's no problem in supporing non-Lisp syntax DSLs in Lisp. You'll need to use some parser/parser generator library as Rainer has mentioned. A good example is esrap that is used to parse markdown (see 3bmd) and also for the pgloader command language which is just an example of an external DSL you're asking about.
From Let Over Lambda, there is an implementation of Perl style regular expressions: http://letoverlambda.com/index.cl/guest/chap4.html#sec_4.
Also there are several attempts at making a "non-lispy" version of Lisp, the main one being the Readable Lisp S-expression Project: http://readable.sourceforge.net/.
One implementation-specific solution that sticks out (if you want to use Scheme rather than CL) is Gambit Scheme's built-in support for infix syntax via its SIX-script extension.
This provides a rich set of loosely C-like operators and syntax forms, which can either be used out-of-the-box to write code in a C-like style, or redefined to mean whatever you want (you can easily redefine e.g. the function definition format, if you aren't a fan of type name(args) {}). for, case, := and so on (even goto) are all already present and ready to mean whatever you need.
The actual core of the syntax (operator precedence, expressions vs. statements) is fixed, but you can assign things like a Scheme binding construct to the s-expression produced by an operator for a reasonably large amount of freedom.
a = b * c;
is translated by the reader into
(six.x=y (six.identifier a) (six.x*y (six.identifier b) (six.identifier c)))
You can then override the definitions of those macros with your own to make the syntax do whatever you want. Turning the C-style base into a Haskell-looking functional language isn't too hard (strategically redefine = and -> and you're halfway there...).
Anyone know what is included in the racket/base language. I am looking to compare the racket/base namespace definitions with the R7RS draft to get a first hand idea of how divergent Racket is from Scheme.
The difference is going to be huge, just like any other practical Scheme implementation. To give you a rough idea, I see more than 1300 identifiers from racket/base, and racket goes up to over 2000. Also, note that comparing the names is not going to be the whole story -- there are additional differences, like the fact that Racket uses immutable pairs by default, and like the fact that you get guaranteed left-to-right evaluation order.
A quick way to get the lists yourself for the former would be to make sure that XREPL is installed (have your ~/.racketrc file contain (require xrepl)), then start Racket with racket/base as the REPL language, and use the ,ap (apropos) command with no arguments so it shows you all of the bound names:
$ racket -I racket/base
Welcome to Racket v5.2.1.
-> ,ap
To read about the names, you can use the ,doc command, or just use the search box in the docs.
According to The Racket Reference:
Unless otherwise noted, the bindings defined in this manual are exported by the racket/base and racket languages.
Unfortunately that is not terribly helpful since it is a large reference manual. But, since you are comparing R7RS to Racket, it may be useful to just browse through the whole reference to get an idea of what is available.
I've got a bunch of "legacy" Guile Scheme code that I want to get running in the Racket Scheme IDE. There appear to be enough differences to make this a non-trivial exercise. (My level of Scheme knowledge is the level to complete the The Little Schemer).
My question is:
What are the differences between Guile Scheme and Standard Scheme (in the Racket IDE)?
In light of these differences, in general, what are the steps I'll need to take to convert some Guile Scheme Code to standard Scheme?
Additional: (happy with divergence between Racket Scheme and R5RS/R6RS) - what I want is to get 'something' to run in the Racket IDE - rather than the Racket language.
If by "Standard Scheme (in the Racket IDE)," you mean the Racket language, i.e., what you get when you prefix your code with #lang racket, then the top four differences to look out for are:
a different module system
a different macro system (depending on how old your code is)
immutable cons-cells (unless you import mutable ones)
no one-armed ifs in Racket (use when)
To port code from Guile to Racket, find out which files are "at the bottom" of your dependencies, i.e., find the files that do not depend on other files.
Open such a file in Racket, add the line #lang racket at the top, and try to run it.
You will most likely encounter some "unbound identifier" errors.
If you are lucky, the function is present in Racket, but not included in the "racket" language. Search for the name in the Racket documentation, and if you find it, then use (require ...) to import the name into your program.
Then run the program again to find the next error.
Some function are named differently in Guile and Racket, so look up the name in the Guile documentation and see what it does. Then open the Racket documentation on the same subject, and see what it is called in Racket.
In some cases you may have to make bigger changes. If you can't find some piece of functionality in the Racket documentation, then try asking the mailing list. It could be that it simply has a different name, or that somebody implemented it and put it on PLaneT (thus it will no appear in the documentation until you have installed the package).
Example of importing srfi/1 into the R5RS language.
#lang r5rs
(#%require srfi/1)
(xcons 1 2)
Differences from R4RS code to modern Scheme?
One thing to look out for is that in R4RS the empty list '() counted as false, not it is interpreted as true.
See this question for more things to look out for:
Running SICP Pattern Matching Rule Based Substitution Code
See also this list of changes from the R5RS standard:
List of changes from R4RS to R5RS