Traversing Scheme function as a list - reflection

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.

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)))))

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.

LISP How to create a database storing function parameters

A little lisp program i got to write should do the following (copied from my old question: LISP - Program to search a specific function through its parameters):
The program should work in 2 different ways:
You give the program the name of a function and it should return the function parameters.
You enter function parameters and if a function with these parameters exists, it should return the name of the function.
I got the following code:
(defun get-name-by-params (database params)
(let ((matching-entries (remove-if-not (lambda (entry)
(equal (second entry) params))
database)))
(mapcar #'first matching-entries)))
(defun get-params-by-name (database function)
(let ((matching-entries (remove-if-not (lambda (entry)
(equal (first entry) function))
database)))
(flatten(mapcar #'second matching-entries))))
(defun flatten (L)
(if (null L)
nil
(if (atom (first L))
(cons (first L) (flatten (rest L)))
(append (flatten (first L)) (flatten (rest L))))))
With that code i get the following results:
(get-params-by-name '((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result)) 'append)
->(&REST LISTS)
(get-name-by-params '((cons (t t) cons) (list (&rest t) list)) '(&rest t))
->(LIST)
That is in both cases exactly what i need. My last problem with my task is that i need to create a database in which the functions and parameters are stored because i will need to add many more functions to the program.
So i need to create a database which stores the following data
'((cons (t t) cons) (list (&rest t) list) (append (&rest lists) result))
and, if possible, can be processed by the given functions.
Could anybody please give me an example how to create a database for this task?
For experimental and quick projects, I tend to use a simple text file that just stores the s-expression.
A very simple database:
(format open-file-stream "~S" any-sexp)
You can look up an entry using some simple functions.
To look up by (implicit) index:
(defun read-nth-sexp (n file)
(with-open-file
(file-stream file)
(loop for i from 0
for sexp = (read file-stream nil)
do (if (eq n i) (return sexp)))))
To find by key:
(Note: You store the key by just adding it to the sexp anywhere in the structure of the sexp, when you stored it. Later you can get at it by providing the relevant selector function, by default assumed to be #'car.)
(defun find-entry (entry file &key (select #'car))
(with-open-file
(file-stream file)
(loop for sexp = (read file-stream nil)
while sexp
do (if (equal (funcall select sexp) entry)
(return sexp)))))
This works well for upto 10,000's or maybe 100'000s of entries, depending on your hardware. I've had difficulty dealing with anything above half million entries.
I haven't had the need to update my data, and so I never wrote any updation functions but they can be written easily.
For very fast search, I've had success with binary search assuming of course your data has sortable properties.
You could design a database in Lisp vs. using a persistent storage database, and you could save the data in a serialized format in order to load/save the database. You'd be surprised, but some big companies such as Yahoo! did this in the 90's, and many still do it today, vs. using a persistent database such as MySQL. Here is an example of the structure of the program if you want to write the database in Lisp. You could use the CLOS to store functions as instances of that class. You say that you need the function name, and the function parameters. So you could create a class with the attributes "name" and "parameters". Here is an example:
(defclass functions()
((name :accessor func-name
:initarg :name)
(params :accessor func-params
:initarg :params
:initform '(nil))))
We can create a class with slots for the name and parameters as I showed above, and then we can create instances of that class. So if for example I have a function like this:
(defun foo (n lst)
(list foo))
I can should create an instance like this...
(defvar func-1 (make-instance 'functions
:name "foo"
:params '("n" "lst")))
And if I have a function like this:
(defun foo-2(lst n)
(list lst n))
I can create another instance like this:
(defvar func-2 (make-instance 'functions
:name "foo-2"
:params '("lst" "n")))
Now how do we store these instances in a database? We have a few options, but a simple and general example would be to store the instances in a list. We could increase the complexity, or even create our own form of an embedded SQL language using Macros, but to keep it simple, we can just use a list and the find function in order to create a make-shift database. Here is an example of a database and two functions to search that database based on a functions name or parameters:
(defvar *func-db* nil) ;Create an empty list to store the functions
(push func-1 *func-db*)
(push func-2 *func-db*) ;Push a couple of functions to the DB
(defun find-params (name)
(func-params
(find name *func-db*
:test #'string-equal
:key #'func-name)))
(defun find-name (param-list)
(func-name
(find param-list *func-db*
:test #'equal
:key #'func-params))
Now we can create a couple of functions to find the params of a function based on the name we search, or find the name of a function based on the params we enter. I will use Strings in this scenario for a simple illustration, but you should probably use symbols. Here are a couple of examples of how we would search the DB:
CL-USER> (find-params "foo")
("n" "lst")
CL-USER> (find-params "foo-2")
("lst" "n")
CL-USER> (find-name '("n" "lst"))
"foo"
CL-USER> (find-name '("lst" "n"))
"foo-2"
That is how we can make a make-shift database in Lisp. A good book to read would be "Practical Common Lisp". There's a free online version, and in that book, one of the main projects is creating an MP3 database. The most simple example is using a List to store information and then searching it. If you want to save the database for later usage, you can save it to a file, and then load it when you want to use it again. This technique might seem simple, but I've seen big companies use it vs. MySQL. You can even create your own embedded SQL language to search for the information, and since the information is stored in memory it could retrieve results even faster than MySQL if you decided to extend this project and create a web application in Lisp.

why (car ''(a b)) evaluated to 'quote?

I'm a beginner Scheme programmer and I want to enrich my knowledge in functional programming. I programm in DrRacket IDE. Recently I found some interesting piece of code:
(car ''(a b))
Output:
'quote
Can anyone explain me why is it evaluated in this way?
This is because ' is short for (quote ...). So,
(car ''(a b))
is actually
(car (quote (quote (a b))))
Which evaluates to:
'quote
As pointed out by Josh in the comments, The actual result is just quote And the REPL prints an expression that can evaluate to quote in this case 'quote or what is the same as seen above (quote quote).
Remember that 'x (for any expression x) is just shorthand for (quote x), so this code:
(car ''(a b))
Is equivalent to this one:
(car (quote (quote (a b))))
Now it's easy to see that you're evaluating the car of a list that looks like this:
'(quote (a b))
Which gets evaluated to this:
(list 'quote (list 'a 'b))
And if we take the car of the above line we'll get the symbol quote, which is precisely the result that you see printed.
It doesn't!
(car ''(a b))
Which is
(car (quote (quote (a b))))
What happens is that car get evaluated to #<procedure:car> and since it'a procedure every argument gets evaluated once before applying..
(quote (quote (a b))) ; ==> (quote (a b))
Now #<procedure:car> of (quote (a b)) is quote. It's not 'quote. I can prove it. Try wrapping it in display like this: (display (car ''(a b))). The output is just quote
So why do you see 'quote in racket interactions window?
Racket has a feature that you can tweak how data is displayed when the expression results that are not explicitly printed by your program. The standard depends on the language selected and for #!racket it's to not to display the data as is but something that you can evaluate and becomes the data. In the REPL you can evaluate the output and get the same since that mode is in effect.
You can change the behaviour if you choose Choose language in the bottom left select and press Show details. The part output syntax lets you choose amongst 4 ways to "display results" in the interactions window. print is the language default and write is the same you get as when you display the data and what is expected from most Scheme books.

How do I create variables in sequence in common Lisp?

I have the following code inside a function that is reading in a file which is a map. I get an error that *numrows* is an illegal dimension. I think this is because lisp is processing these variables in parallel. How can I fix this?
(setq *numrows* (read map))
(setq *numcols* (read map))
(setq *map* (make-array '(*numrows* *numcols*) :initial-element nil))
You're misdiagnosing the problem. The first argument you're passing to MAKE-ARRAY is a list of two symbols, *NUMROWS* and *NUMCOLS*. However, the first argument to MAKE-ARRAY should be a list of non-negative integers. The easiest way to fix your example is to make a list with the values instead: (list *numrows* *numcols*). So the code would look like this instead:
(setq *numrows* (read map))
(setq *numcols* (read map))
(setq *map* (make-array (list *numrows* *numcols*) :initial-element nil))
You normally wouldn't use setq like this, though. It'd probably be better, depending on the context, to bind those variables with LET*:
(let* ((numrows (read map))
(numcols (read map))
(map-array (make-array (list numrows numcols) :initial-element nil))
; do something with map-array
)

Resources