Accessing a stored list in Racket - scheme

Is there a way to access a stored list in Racket without passing it new data? A list of past responses is stored using the following code in a program I'm working on.
(define (storage response lst)
(cons response lst))
This makes a list by taking a response to a question and a previous list. I don't want to change what's in the list just simply see what's inside it. If other code is needed I will be happy to show what I have.

The standard way to access a list's elements in Racket is by using the first and rest procedures (or equivalently: car and cdr) to recursively iterate over a list. For example, let's say that you want to find out if the list contains the "404" response:
(define responses '("302" "403" "404" "505"))
(define (find-response lst response)
; the list is empty, the element was not found
(cond ((empty? lst)
#f)
; `first` accesses the first element in the list
((equal? (first lst) response)
#t)
(else
; `rest` advances to the next elements in the list
(find-response (rest lst) response))))
(find-response responses "404")
=> #t
(find-response responses "201")
=> #f
Of course, once you learn how this works, you can move and use existing procedures, for example member as suggested in the other answers. Please take a look at the list procedures available for use, you'll see that the most frequent operations are already implemented and at your disposal.

As currently constructed, you created a function called storage that takes response and a list and returns a new list with response as the head and lst as the tail.
If you want to get the head or tail of (storage a l) then you just call (car (storage a l)) or (cdr (storage a l))- it's just a list.

Yes, there is a way to access a stored list without passing it as new data. See page 25, Section 6.3.2 in the Scheme R5RS Specification for a full list of 'list accessing' functions. Racket probably has more; other Scheme versions may have additional ones.
Here is an example. To test if a 'response' has been seen already:
(member response lst)
to count the number of responses:
(length lst)

Related

Syntax Error in Racket equal?

I am trying pass in a list input to conversation and have the function check to see if the first element in another list (keyword) matches to the first element of the list that user passed in. If the two match then output a zero otherwise pass the tail of the inputted list recursively back to itself.
(define keyword '(am I))
(define (conversation input)
(cond
((equal? (car keyword) (car input)) 0)
(else (conversation (cdr input)))))
The error I get is:
car: contract violation
expected: pair?
given: '()
I understand that equal? compares two elements, a pair, but what I do not understand is why it would create an error when the car of both lists are both exactly an element. Any help would be much appreciated, I'm assuming the solution is rather simple but I can't seem to see it.
My goal is create several functions that pattern match and output appropriate dialog but without the use of regular expressions or other libraries. There is no mandate not to use the two mentioned above but I would like to do it without them to get a better understanding of the logic and the code. Thanks for the help!
The first thing to consider is that you have no condition of failure. You assume there's either a match now with the car, or there will be a match later with the cdr. But there may be no match at all, and you will cdr down your list until your list is '(). As there is no such thing as the car of '() you are getting an error when you try to extract it. Therefore the first thing to do is make sure you've handled this case. I don't know what you intend to do in this case, so I have made the procedure return #f.
Next you consider what to do if the symbols do match. In your case you are choosing to return 0. This part seems to have no problems.
Finally, we consider what to do if the cars do not match. In this case we continue searching the input. This part seems to have no problems.
(define (conversation input)
(cond ((null? input) #f)
((eq? (car input) (car keyword))
0)
(else
(conversation (cdr input)))))

Save an object to a binary file and retrieve it later

I have following class:
(define stackClass%
(class object%
(super-new)
(init-field (mystack '(A B C)))
(define/public (push n)
(set! mystack (cons n mystack)))
(define/public (pop)
(cond [(empty? mystack) #f]
[else (define res (car mystack))
(set! mystack (cdr mystack))
res] ))
(define/public (get)
mystack) ))
I create an object and alter it:
(define sc (new stackClass%))
(send sc push 1)
(send sc push 2)
Can I now save this "sc" object as a binary file to be retrieved later? If yes, would I need to save the stackClass% also? (In reality the objects may be much more complex and may even have other objects, images, files etc, in addition to simple numbers or text).
I checked the documentation at different places including http://docs.racket-lang.org/binary-class/index.html but could not understand how to achieve this.
The racket object system has support for serialization. That means your class must be defined with define-serializable-class and it needs to implement externalize and internalize. externalize needs to return a representation that only consist of serializable data (except instances og its own class) and it seems the system will do the rest. internalize method needs to take that format and set the members on a freshly created instance accordingly.
Racket seem to add some information so that the rest happens magically as long as the class is defined in the system that unserializes the data.

Procedure expected 2 arguments plus optional arguments with keywords

I am running a program using the command line version of Racket.
At some point I call:
(sort(some-function (car set) (POWER (cdr set))))
The sort procedure looks like this:
(define (sort l)
(if (null? l)
'()
(insert (car l)
(sort (cdr l)))))
But when I run the program, it says:
Welcome to Racket v5.1.1.
> > > > > > procedure sort: expects 2 arguments plus optional arguments with keywords #:cache-keys? and #:key, given 1: (some-function (car set) (POWER (cdr set)))
Why does it say sort expects two arguments? When running it through the Racket GUI, I have no problems.
It seems that you're trying to execute Racket's built-in sort procedure, which in fact receives 2 arguments (a list and a comparison procedure) plus optional arguments with keywords.
Make sure that the sort procedure you defined is in fact the one that gets called, by defining it first before the point where you're actually using it, or just to be sure rename it to say, mysort and use that name consistently - because anyway it's not always a good idea to overwrite existing procedures.

multiple expressions after identifer error

Here is the code:
(define path (lambda lst start end)
(let ((nodes (car lst))
(edges (cdr lst)))))
Why is this causing an error?
You misused lambda keyword, and function body isn't complete.
(define path (lambda (lst start end)
(let ((nodes (car lst))
(edges (cdr lst)))
; here should be expression, i think with lst, nodes and edges
)))
Note: when you say "Can anyone help me with this error", please include what error message you're seeing. Your whole program can't be an error in itself. But it can contain errors, and when you try running it, it can produce error messages.
I'm assuming you saw error messages. Include those too, next time. Also tell us what you expected to see. Did you expect to get the error you're seeing?
The reason why you should include the actual error message is because the problem you're seeing may not even have anything to do with what you think the problem is. In that case, the error message allows us to make sure we're on the right track in solving your problem.
Looking at your program, I think it's syntactically incomplete. A let needs to have at least a body, or else it's ungrammatical according to the language's rules. There's no body present in:
(let ((nodes (car lst))
(edges (cdr lst)))
)
(An analogous error message in a language like C would occur if you try to use the if statement but not include a test.)
At the very least, you can include some kind of placeholder until you figure out what you really need to put in there. For example:
(let ((nodes (car lst))
(edges (cdr lst)))
"fixme")
should at least make the program a syntactically acceptable one. Though it won't do anything too useful yet.

How to examine list of defined functions from Common Lisp REPL prompt

I'm evaluating/testing a browser based application presumably written in common lisp. Apart from the browser based interface, the software provides a 'Listener' window with a 'CL-User >' REPL prompt.
I wish to examine the list of functions, symbols, and packages from the REPL prompt. So that I could co-relate the frontend functionality with what is exposed via the REPL.
Google search is futile for me as it leads to tutorials and resources that teaches lisp step-by-step.
Any hints, pointers on examining the state via REPL will be much appreciated.
If you don't know what symbols you're looking for, but do know what packages you want to search, you can drastically reduce the amount of searching you have to do by only listing the symbols from those specific packages:
(defun get-all-symbols (&optional package)
(let ((lst ())
(package (find-package package)))
(do-all-symbols (s lst)
(when (fboundp s)
(if package
(when (eql (symbol-package s) package)
(push s lst))
(push s lst))))
lst))
(get-all-symbols 'sb-thread) ; returns all the symbols in the SB-THREAD package
The line (get-all-symbols 'sb-thread) does just that.
If you have an idea about what type of symbols you're looking for, and want to take a guess at their names, you can do this
(apropos-list "mapc-") ; returns (SB-KERNEL:MAPC-MEMBER-TYPE-MEMBERS SB-PROFILE::MAPC-ON-NAMED-FUNS)
(apropos-list "map" 'cl) ; returns (MAP MAP-INTO MAPC MAPCAN MAPCAR MAPCON MAPHASH MAPL MAPLIST)
(apropos-list) returns all symbols whose name contains the string you pass in, and takes an optional package to search.
As far as figuring out what all those symbols do, well, try this: http://www.psg.com/~dlamkins/sl/chapter10.html
To list everything:
(apropos "")
To list everything from a specific package add 'project-name:
(apropos "" 'quickproject)
To list all the packages (duh):
(list-all-packages)
To find functions exported from a particular package:
(loop for x being the external-symbol of "CL" when (fboundp x) collect x)
(let ((lst ()))
(do-all-symbols (s lst)
(when (fboundp s) (push s lst)))
lst)
Pretty much taken as-is from here.
Maybe something like this:
(defun get-symbols-in-package (&optional (package *package*))
(let ((lst ()))
(do-symbols (s package)
(push s lst))
lst))
Use as (get-symbols-in-package) or (get-symbols-in-package 'foo) ...

Resources