How do I make a module in PLT Scheme? - functional-programming

I tried doing this:
#lang scheme
(module duck scheme/base
(provide num-eggs quack)
(define num-eggs 2)
(define (quack n)
(unless (zero? n)
(printf "quack\n")
(quack (sub1 n)))))
But I get this error:
module: illegal use (not at top-level) in:
(module duck scheme/base (provide num-eggs quack) (define num-eggs 2) (define (quack n) (unless (zero? n) (printf "quack\n") (quack (sub1 n)))))
what is the correct way?

You should remove the (module duck scheme/base line (and the closing paren).
When you start your code with #lang scheme, it's effectively putting your code in a module that uses the scheme language. You can also use #lang scheme/base if you want the smaller language instead.
(To really get convinced, do this:
(parameterize ([read-accept-reader #t])
(call-with-input-file "some file" read))
over some source file that uses #lang and see what you get.)
(And BTW, the title of your question is bad -- it should be "PLT Scheme", since this is not relevant to other implementations.)

Related

Cant use let variables in when condition [duplicate]

This question already has an answer here:
Lisp, instructions not working in defun [duplicate]
(1 answer)
Closed 8 months ago.
I have following code snippet:
(defun upsi()
(let ((firstpos (car *old-list*)) (secondpos (car(cdr *old-list*))))
(let ((found nil)(secondlocation (list (car (cdr firstpos)) (car secondpos))))
(when (= (found nil))
(setq *new-list* (list(firstlocation)))))))
This gives me following error "The function COMMON-LISP-USER::FOUND is undefined"
But when I try this code, it works perfectly.
(defun upsi()
(let ((firstpos (car *stenches*)) (secondpos (car(cdr *stenches*))))
(let ((found nil)(secondlocation (list (car (cdr firstpos)) (car secondpos))))
(print found)
(print secondlocation))))
What is the cause, that I cant use the variables found and secondlocation in my when condition. In fact I also cant use them in a loop. But when I print them I dont get any errors. It looks to me that they are out of scope but I dont understand why ?
I am just into common-lisp but this confuses me so much^^
Parentheses carry semantic meaning in Common Lisp, and you can't just place them anyplace you like as you can in many other languages. The first position of a list expression is interpreted as an identifier for a function, and that function is called on the arguments; this will fail when there is no such function.
In (when (= (found nil)) you are calling the function found, which doesn't exist. You probably meant (when (= found nil)), but this wouldn't work either because = is meant for comparing numbers in Common Lisp. You could use the null predicate, or it might be better to use an unless form instead of when.
The same problem also seems to occur in the body of the when form: (list (firstlocation)). Here the parentheses indicate that firstlocation is a function that you want to call. I don't think that this is the case given that secondlocation is a list, but I don't see firstlocation defined anyplace so I could be wrong.
A couple of other observations: there is a let* form that allows you to use identifiers which were previously bound in the same form. There is also cadr to use instead of calling car on the result of calling cdr, or you could use second. As presented here, your code is very difficult to read and reason about; you should really use an editor that properly indents your code, and look at some examples of lisp written by experienced programmers to get a feel for what it should look like.
Here are a couple of rewritten versions of your code; the first uses null and the second uses unless. I have assumed that firstlocation is a list, and just renamed secondlocation to firstlocation since secondlocation isn't used in the posted code for the sake of getting the code to function.
(defvar *old-list* '())
(defvar *new-list* '())
;; Using `let*`, `cadr`, and `when` with `null`:
(defun upsi()
(let* ((firstpos (car *old-list*))
(secondpos (car (cdr *old-list*))) ; could also use `cadr` or `second`
(found nil)
(firstlocation (list (cadr firstpos) (car secondpos))))
(when (null found)
(setq *new-list* (list firstlocation)))))
;; Using `let*`, `second`, and `unless`:
(defun upsi()
(let* ((firstpos (car *old-list*))
(secondpos (car (cdr *old-list*))) ; could also use `cadr` or `second`
(found nil)
(firstlocation (list (second firstpos) (car secondpos))))
(unless found
(setq *new-list* (list firstlocation)))))

Define a constant array of struct known at compilation-time

In my program I have constant strings, the values are known at compilation time. For each offset there are currently 2 associated strings. I first wrote the following code:
(eval-when (:compile-toplevel :load-toplevel :execute) ;; BLOCK-1
(defstruct test-struct
str-1
str-2))
(eval-when (:compile-toplevel) ;; BLOCK-2
(defparameter +GLOBAL-VECTOR-CONSTANT+ nil) ;; ITEM-1
(let ((vector (make-array 10
:initial-element (make-test-struct)
:element-type 'test-struct)))
(setf (test-struct-str-1 (aref vector 0)) "test-0-1")
(setf (test-struct-str-2 (aref vector 0)) "test-0-2")
(setf +GLOBAL-VECTOR-CONSTANT+ vector)))
(format t "[~A]~%" (test-struct-str-1 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
(format t "[~A]~%" (test-struct-str-2 (elt +GLOBAL-VECTOR-CONSTANT+ 0)))
This seems to work as it returns the following:
[test-2-1]
[test-2-2]
In BLOCK-1 the struct containing the data is defined, for compile-time, load-time and execute-time. In BLOCK-2, the code which create a vector and sets the values is executed, at compile-time.
But I have the following concerns:
This code seems unnecessary verbose
The strings are stored in a structure
I need to manually set the offset of each values ((aref vector 0), (aref vector 1), etc).
When I set ITEM-1 inside BLOCK-1 instead of BLOCK-2 I get an error in SBCL which I don't understand
What is the idiomatic way to define complex constants in Common Lisp?
It's not really clear what you want to do from your question.
First important note: your code is seriously broken. It's broken because you define +global-vector-constant+ only at compile time but refer to it later than that. If you compile this file and then load that compiled file into a cold image you will get errors.
It is absolutely critical when dealing with things like this to make sure that your code will compile in a cold Lisp. One of the classic problems with resident environments (which CL isn't really, compared to the way Interlisp-D was for instance) is to end up with systems which you can't cold build: I'm pretty sure I worked for several years with an Interlisp-D sysout that no-one knew how to cold build any more.
If what you want is an object (an array, for instance) whose initial value is computed at compile time and then treated as a literal, then the answer to that is, in general, a macro: macros are exactly functions which do their work at compile time, and so a macro can expand to a literal. In addition it must be the case that the object you want to be a literal is externalizable (which means 'can be dumped in compiled files') and anything involved in it is known about at compile time. Instances of some classes are externalizable by default, those of some other classes can be made externalizable by user code, and some are not externalizable at all (for instance functions).
In quite a lot of simple cases, like the one you gave, if I understand it, you don't really need a macro, and in fact you can almost always get away without one, although it may make your code easier to understand if you do use one.
Here is a simple case: many arrays are externalizable if their elements are
(defparameter *my-strings*
#(("0-l" . "0-r")
("1-l" . "1-r")))
This means that *my-strings* will be bound to a literal array of conses of strings.
A more interesting case is when the elements are, for instance structures. Well, structures are also externalizable, so we can do that. And in fact it's quite possible, still, to avoid a macro, although it now becomes a bit noisy.
(eval-when (:compile-toplevel :load-toplevel :execute)
(defstruct foo
l
r))
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
Note that the following won't work:
(defstruct foo
l
r)
(defparameter *my-strings*
#(#s(foo :l "0-l" :r "0-r")
#s(foo :l "1-l" :r "1-r")))
It won't work because, at compile time, you are trying to externalize instances of a structure which is not yet defined (but it probably will work if the Lisp is not cold, and you might even be able to reload the compiled file you made that way). Again, in this case you can avoid the eval-when in a larger system by ensuring that the file which defines the foo structure is compiled and loaded before the file with the defparameter is loaded.
And even in more complex cases you can escape using a macro. For instance for many sorts of objects which are normally not externalizable you can teach the system how to externalize them, and then splice the object in as a literal using #.:
(eval-when (:compile-toplevel :load-toplevel :execute)
;; Again, this would be in its own file in a bigger system
(defclass string-table-wrapper ()
((strings)
(nstrings :initform 0)))
(defmethod initialize-instance :after ((w string-table-wrapper)
&key (strings '()))
(let ((l (length strings)))
(when l
(with-slots ((s strings) (n nstrings)) w
(setf s (make-array l :initial-contents strings)
n l)))))
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(make-load-form-saving-slots w :slot-names '(strings nstrings)
:environment environment))
) ;eval-when
(defgeneric get-string (from n)
(:method ((from string-table-wrapper) (n fixnum))
(with-slots (strings nstrings) from
(assert (< -1 n nstrings )
(n)
"bad index")
(aref strings n))))
(defparameter *my-strings*
#.(make-instance 'string-table-wrapper
:strings '("foo" "bar")))
Note that, of course, although the value of *my-strings* is a literal, code ran to reconstruct this object at load-time. But that is always the case: it's just that in this case you had to define what code needed to run. Instead of using make-load-form-saving-slots you could have done this yourself, for instance by something like this:
(defmethod make-load-form ((w string-table-wrapper) &optional environment)
(declare (ignore environment))
(if (slot-boundp w 'strings)
(values
`(make-instance ',(class-of w))
`(setf (slot-value ,w 'strings)
',(slot-value w 'strings)
(slot-value ,w 'nstrings)
,(slot-value w 'nstrtrings)))
`(make-instance ',(class-of w))))
But make-load-form-saving-slots is much easier.
Here is an example where a macro does perhaps least make reading the code easier.
Let's assume you have a function which reads an array of strings from a file, for instance this:
(defun file-lines->svector (file)
;; Needs CL-PPCRE
(with-open-file (in file)
(loop
with ltw = (load-time-value
(create-scanner '(:alternation
(:sequence
:start-anchor
(:greedy-repetition 1 nil
:whitespace-char-class))
(:sequence
(:greedy-repetition 1 nil
:whitespace-char-class)
:end-anchor)))
t)
for nlines upfrom 0
for line = (read-line in nil)
while line
collect (regex-replace-all ltw line "") into lines
finally (return (make-array nlines :initial-contents lines)))))
Then, if this function is available at macroexpansion time, you could write this macro:
(defmacro file-strings-literal (file)
(check-type file (or string pathname) "pathname designator")
(file-lines->svector file))
And now we can create a literal vector of strings:
(defparameter *fl* (file-strings-literal "/tmp/x"))
However you could perfectly well instead do this:
(defparameter *fl* #.(file-lines->svector "/tmp/x"))
Which will do the same thing, but slightly earlier (at read time, rather than at macroexpansion/compile time). So this is gaining nothing really.
But you could also do this:
(defmacro define-stringtable (name file &optional (doc nil docp))
`(defparameter ,name ,(file-lines->svector file)
,#(if docp (list doc) nil)))
And now your code reads like
(define-stringtable *st* "my-stringtable.dat")
And that actually is a significant improvement.
Finally note that in file-lines->svector that load-time-value is used to create the scanner exactly once, at load time, which is a related trick.
First of all, your let code can be simplified to
(defparameter +global-vector-constant+
(let ((vector ...))
...
vector))
Second, you can also do
(defparameter +global-vector-constant+
(make-array 10 :element-type 'test-struct :initial-content
(cons (make-test-struct :str-1 "test-0-1" :str-2 "test-0-2")
(loop :repeat 9 :collect (make-test-struct)))))
Note that the benefit of :element-type 'test-struct is generally limited to code self-documentation (see upgraded-array-element-type)

Is there a way to find out how the primitive functions (built-in) where exactly defined inside SBCL?

I am learning Common Lisp using Emacs, SBCL and Slime.
I would like to know exactly what is the code definition of the built-in functions.
I know how to use (documentation ...) and (describe ...). However, they provide only high level information. I would like to see the code details.
For instance, take the nth built-in function.
Documentation gives us:
CL-USER> (documentation 'nth 'function)
"Return the nth object in a list where the car is the zero-th element."
Describe gives me:
CL-USER> (describe 'nth)
COMMON-LISP:NTH
[symbol]
NTH names a compiled function:
Lambda-list: (SB-IMPL::N LIST)
Declared type: (FUNCTION (UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
Derived type: (FUNCTION (T T) (VALUES T &OPTIONAL))
Documentation:
Return the nth object in a list where the car is the zero-th element.
Inline proclamation: MAYBE-INLINE (inline expansion available)
Known attributes: foldable, flushable, unsafely-flushable
Source file: SYS:SRC;CODE;LIST.LISP
(SETF NTH) names a compiled function:
Lambda-list: (SB-KERNEL::NEWVAL SB-IMPL::N LIST)
Derived type: (FUNCTION (T UNSIGNED-BYTE LIST) (VALUES T &OPTIONAL))
Inline proclamation: INLINE (inline expansion available)
Source file: SYS:SRC;CODE;SETF-FUNS.LISP
(SETF NTH) has a complex setf-expansion:
Lambda-list: (SB-IMPL::N LIST)
(undocumented)
Source file: SYS:SRC;CODE;DEFSETFS.LISP
; No value
I would like to see something like:
(unknown-command 'nth)
Which would return something like:
(defun nth (x xs)
(if (equal x 0)
(car xs)
(my-nth (- x 1) (cdr xs))))
Lisp languages are fantastic and have a huge ecossystem built by awesome programmers. I hope there is some tool or command for that.
Thanks
First, some general clarifications
In your own code, hitting Meta-. should take you to the source of the code
This will also "just work" for libraries installed via Quicklisp.
Now for SBCL code itself:
If the code is in the "expected place", hitting Meta-. on built-in functions (like nth in your example above) will also take you to its source. I believe the default is /usr/share/sbcl-source/src/code/ but there's possibly a way to configure it.
However, there's another practical way to view this: if you look at the output of (describe ...) above, the line was:
Source file: SYS:SRC;CODE;LIST.LISP
Note: not the last line, that is for (setf nth), something slightly different
This tells you which file in the SBCL source code you can expect to find the function definition.
So, within [the repo](https:/ /github.com/sbcl/sbcl/tree/master/src), if you locate src/code/list.lisp, you should find the definition you're looking for; reproducing here:
(defun nth (n list)
"Return the nth object in a list where the car is the zero-th element."
(declare (explicit-check)
(optimize speed))
(typecase n
((and fixnum unsigned-byte)
(block nil
(let ((i n)
(result list))
(tagbody
loop
(the list result)
(if (plusp i)
(psetq i (1- i)
result (cdr result))
(return (car result)))
(go loop)))))
(t
(car (nthcdr n list)))))
When such information is available, it should be accessible via function-lambda-expression :
* (FUNCTION-LAMBDA-EXPRESSION #'nth)
(LAMBDA (SB-IMPL::N LIST)
(DECLARE (SB-INT:EXPLICIT-CHECK)
(OPTIMIZE SPEED))
(BLOCK NTH
(TYPECASE SB-IMPL::N
((AND FIXNUM UNSIGNED-BYTE)
(BLOCK NIL
(LET ((SB-IMPL::I SB-IMPL::N) (SB-IMPL::RESULT LIST))
(TAGBODY
LOOP
(THE LIST SB-IMPL::RESULT)
(IF (PLUSP SB-IMPL::I)
(PSETQ SB-IMPL::I (1- SB-IMPL::I)
SB-IMPL::RESULT (CDR SB-IMPL::RESULT))
(RETURN (CAR SB-IMPL::RESULT)))
(GO LOOP)))))
(T (CAR (NTHCDR SB-IMPL::N LIST))))))
NIL
NTH
However, it is not always available, in which case you would have to go to the SBCL source code repository.

Error with define in Racket

I just discovered Racket a few days ago, and I'm trying to get more comfortable with it by writing a little script that generates images to represent source code using #lang slideshow.
I know that when programming in a functional paradigm it's good practice to create almost all your variables with let, but I find that it introduces too many levels of nesting and that Racket's let has an overcomplicated API which requires superfluous parentheses. I'm sure this is to remove ambiguity when using let in more powerful ways, but for my purposes it's just an annoyance. Consequently, I'm creating all my variables with define, and writing blocks with begin if I need to (such as in the body of an if statement).
The problem is that I've repeatedly been getting what seem to be very mysterious errors. I'm sure I'm just making some silly beginner's mistake, being new to the language, but I really can't seem to find the source of the complaint.
Here's the offending code:
(define sub-code (foldr ht-append (rectangle 0 0) (map internal-style (rest code))))
although what we're defining sub-code to seems pretty irrelevant. If I replace it with
(define sub-code '())
I receive the same error. DrRacket is saying that define is being used in an expression context. I understand what this error would normally mean - IE that it would raise when you write code like (print (define x 10)), but I can't see what would trigger it here.
If it helps, this define is at the beginning of a begin block, inside an if statement
(if (list? code)
(begin
(define sub-code '())
; a few more define statements and finally an expression ))
The specific error message DrRacket is printing is
define: not allowed in an expression context in: (define sub-code (quote ()))
I thought maybe define isn't allowed in begin blocks, but I checked the docs and one of the examples for begin is
(begin
(define x 10)
x)
So I don't really know what to do. Thanks in advance!
Definitions are allowed in a 'body' context, like in lambda and let among others. The consequent and alternate clauses of if are not body contexts; they are expression contexts and therefore definitions are not allowed.
begin is special - begin in a body context allows definitions, but begin in an expression contexts forbids definitions. Your case falls in to the later.
For example:
(define (foo . args) #| body context #|)
(define foo (lambda args #| body context |#))
(define (foo . args)
(let (...)
#| body context |#))
Syntactic keywords that requires expressions: if, cond, case, and, or, when, unless, do, begin. Check out the formal syntax in any Scheme report (r{4,5,6,7}rs); look for <body>, <sequence>, <command>, and <expression>.
Also, if you need a body context in an expression, just wrap a let syntactic form, as such:
(if test
(let ()
(define foo 'foo)
(list foo foo))
alternate)
As GoZoner explained, you can't use define in an expression context.
What could you do instead?
Use let:
(if (list? code)
(let ([x '()])
x)
...
Or it would work with an "empty" let and define:
(if (list? code)
(let ()
(define x '())
x)
...
But that's a bit silly.
Or use cond and define:
(cond [(list? code)
(define x '())
x]
...
This last way -- using cond and define -- is closest to what the current Racket style guide recommends.
Here's more details, from the Racket docs.
The different contexts are required because macros must expand differently, depending on which language forms are allowed.
As others have said, definitions are not allowed in expression contexts ("expr ..." in the docs), but are ok in other contexts.
In other doc entries, "body ..." indicates an internal-definition context (guide, reference), for example in lambda bodies, and "form ..." indicates all non-expression contexts, like in the docs for begin.
Or you could wrap the expressions in (begin)
e.g.(begin
(define x 10)
(define y 100)
(define z 1000))

Traversing Scheme function as a list

Isn't it possible to treat functions in Scheme as any other list?
Basically, what I want do to is something like this:
(define (foo) "hello")
(cdr foo) ; or similar, should return the list ((foo) "hello")
I've found a similar discussion about this, and I feel a bit disappointed if this is not possible with Scheme. If so, why is this impossible? Is it possible in other lisps?
EDIT: Changed (cdr 'foo) to (cdr foo) -- it was misleading. I'm asking, why can't I access a function as a list?
I have often wanted to be able to do the same thing csl.
Below is a quick example of how you could go about doing this in mzscheme.
DrScheme 4.2
(module qdefine mzscheme
(provide ;(all-from-except mzscheme let)
(rename define olddefine)
(rename quote-define define)
(rename quote-cdr cdr)
(rename quote-car car))
(define define-list '())
(define define-list-add
(lambda (key value)
(set! define-list (cons `(,key ,value) define-list))))
(define-syntax quote-define
(syntax-rules ()
((_ (pro-name args ...) body ...)
(begin
(define (pro-name args ...) body ...)
(define-list-add pro-name '((pro-name args ...) body ...))))
((_ pro-name pro) (begin
(define pro-name pro)
(define-list-add pro-name 'pro)))
))
(define quote-cdr (lambda (lst)
(if (procedure? lst)
(cdr (cadr (assoc lst define-list)))
(cdr lst))))
(define quote-car (lambda (lst)
(if (procedure? lst)
(car (cadr (assoc lst define-list)))
(car lst))))
)
(require 'qdefine)
(define testfunc (lambda (args) args))
(cdr testfunc)
(car testfunc)
(define (testfunc2 test) 'blah)
(cdr testfunc2)
(car testfunc2)
(define testlist '(1 2 3 4 5 6 'a))
(cdr testlist)
(car testlist)
Outputs:
((args) args)
lambda
('blah)
(testfunc2 test)
(2 3 4 5 6 'a)
1
>
Your define form is not a function but a function definition. In fact, it is a shorthand for
(define foo
(lambda ()
"hello"))
Lambda can be thought of as a "compiler invocation". In this case, it produces a function which returns that string. Define then binds this function to the symbol 'foo.
Compare this to
(define foo "hello")
which binds just the string to the symbol 'foo. What would (cdr foo) return?
Now, it is imaginable that some Scheme implementation actually saves or has the option to save the lambda form when binding a function to a symbol. You will have to check the documentation, but the kind of pure interpretation this implies surely would have an impact on performance.
If you manage to get this, though, it will return the lambda form, not the define form.
MIT Scheme has the ability to do this. (If you really want, comment on this and I'll give you the code. I had to find some undocumented functions to make it happen.)
However, it's not in the Scheme language definition, so implementations don't have to allow it. The reason for this is that in order to make functions faster, a good Scheme implementation will modify the functions. This means both rewriting them in a different language (either machine code or something fairly low-level) and taking out any bits you don't need - for instance, the + function must in general check whether its arguments are numbers, and if so, what sort of numbers, but if your function is a loop which calls +, you can just check once at the beginning, and make the function a lot faster.
Of course, you could still keep the lists around without too much trouble, even with all of these things. But if you tried to modify the lists, how would it work?
(Again, you could make it work. It would just be more work for implementers, and since it's not usually used in programs, most people probably just don't want to bother.)
In guile,
guile> (define (foo bar) 'baz)
guile> (procedure-source foo)
(lambda (bar) (quote baz))
guile> (cdr (procedure-source foo))
((bar) (quote baz))
guile>
'foo evaluates to a symbol, you can't take the CDR of a symbol.
What you may want to do is (cdr foo), but this does not work. The value of a FOO is a procedure, not a list.
You might be able to access the function as a list using pp or pretty-print. That said, you might also need to run your code in debug mode. This is very implementation dependent however. I know it can work in Gambit-C.
(define (foo) ...) produces a compiled object, and it's a value - a procedure.
You cannot iterate over it because it is not an s-expression.
Like what other suggested, you should check out your programming environment and see
if it has any facilities for such tasks.

Resources