common lisp (multiple) values both true and false? - common-lisp

I seem to have a cat-in-a-box kind of problem here
The following code should, given a key and a hash-table, return the value corresponding to the key, or an error if the key is not present in the map:
(defun get-graph-node (key graph)
(let ((result (gethash key graph)))
(if (nth-value 1 result)
(nth-value 0 result)
(error "no node matches the key"))))
And for the most part it does, but I have this weird situation where running:
(gethash 0 *g*)
returns
#S(GRAPH-NODE$
:DATA "("$
:EDGES (#S(GRAPH-NODE :DATA "b" :EDGES NIL)$
#S(GRAPH-NODE :DATA "a" :EDGES NIL)))
T
But
(get-graph-node 0 *g*)
Signals the error defined in get-graph-node
inspecting *g* gives me this:
Count: 5
Size: 16
Test: EQL
Rehash size: 1.5
Rehash threshold: 1.0
[clear hashtable]
Contents:
0 = #S(GRAPH-NODE :DATA "(" :EDGES (#S(GRAPH-NODE :DATA "b" :EDGES NIL) #S(GRAPH-NODE :DATA "a" :EDGES NIL)))
[remove entry]
1 = #S(GRAPH-NODE :DATA "a" :EDGES NIL) [remove entry]
2 = #S(GRAPH-NODE :DATA "|" :EDGES (#S(GRAPH-NODE :DATA ")" :EDGES (NIL)))) [remove entry]
3 = #S(GRAPH-NODE :DATA "b" :EDGES NIL) [remove entry]
4 = #S(GRAPH-NODE :DATA ")" :EDGES (NIL)) [remove entry]
So the key 0 should be in the map?
A giant tip of my hat to the gentleman whom can tell me what I am missing.

When assigning the result of gethash to the variable result, you are only storing the first of the multiple values returned by the function. To store them both, you should do something like this:
(defun get-graph-node (key graph)
(multiple-value-bind (result exists)
(gethash key graph)
(if exists
result
(error "no node matches the key"))))

Related

Why does the Lisp reader return `(list 1 2 3)` instead of `(1 2 3)` when using reader macros?

Recently, I tried to understand reader macros better. I have read an article about using reader macros to read in objects in JSON format.
With slightly adapted code from above article (it only reads (or is supposed to read) arrays [1,2,3] into lists (1 2 3))
(defun read-next-object (separator delimiter &optional (input-stream *standard-input*))
(flet ((peek-next-char ()
(peek-char t input-stream t nil t))
(discard-next-char ()
(read-char input-stream t nil t)))
(if (and delimiter (char= (peek-next-char) delimiter))
(progn
(discard-next-char)
nil)
(let* ((object (read input-stream t nil t))
(next-char (peek-next-char)))
(cond
((char= next-char separator) (discard-next-char))
((and delimiter (char= next-char delimiter)) nil)
(t (error "Unexpected next char: ~S" next-char)))
object))))
(defun read-separator (stream char)
(declare (ignore stream))
(error "Separator ~S shouldn't be read alone" char))
(defun read-delimiter (stream char)
(declare (ignore stream))
(error "Delimiter ~S shouldn't be read alone" char))
(defun read-left-bracket (stream char)
(declare (ignore char))
(let ((*readtable* (copy-readtable)))
(set-macro-character #\, 'read-separator)
(loop
for object = (read-next-object #\, #\] stream)
while object
collect object into objects
finally (return `(list ,#objects)))))
the intent is to call read on strings and have it produce Lisp lists.
With following test code I get:
(with-input-from-string (stream "[1,2,3]")
(let ((*readtable* (copy-readtable)))
(set-macro-character #\[ 'read-left-bracket)
(set-macro-character #\] 'read-delimiter)
(read stream)))
;; => (LIST 1 2 3)
I expected to get (1 2 3) instead.
Now, when I change the current readtable "permanently", i.e. call set-macro-character in the top-level, and type [1,2,3] at the prompt, I get indeed (1 2 3).
Why, then, does
(with-input-from-string (stream "(1 2 3)")
(read stream)))
;; => (1 2 3)
give the "expected" result? What am I missing? Is there some eval hidden, somewhere? (I'm aware of the quasi-quote above, but some in-between reasoning is missing...)
Thanks!
EDIT:
Using
(defun read-left-bracket (stream char)
(declare (ignore char))
(let ((*readtable* (copy-readtable)))
(set-macro-character #\, 'read-separator)
(loop
for object = (read-next-object #\, #\] stream)
while object
collect object)))
I get what I expect. Entering '[1,2,3] at the REPL behaves like entering "real" lists.
Reading from strings also works as intended.
You have
(return `(list ,#objects))
in your code. Thus [...] is read as (list ...).
Next if you use the REPL and evaluate
> [...]
Then it is as you were evaluating
> (list 1 2 3)
which returns (1 2 3).

Dr. Racket, help getting element from a list

I am working on a finite state machine in Dr. Racket, and need some help extracting the next state in my transition function.
Right now, I am not checking to make sure the chars in the string match the alphabet, or that the final state is in the list of final states, or any of that until I can get the transition from state to state recursively.
Here is where I am at right now:
#lang racket
(require math/array)
(define in_string (list "a" "b" "b" "b"))
(define alphabet (list "a" "b"))
(define initial_state 0)
(define final_states (list 2))
(define delta_fn (list
(list 0 "a" 0)
(list 0 "b" 1)
(list 1 "a" 0)
(list 1 "b" 1)))
(define current_state initial_state)
(define (transition current_state in_string delta_fn)
(writeln current_state)
(writeln in_string)
(writeln delta_fn)
(cond
[(empty? in_string) (writeln current_state)]
[else
(let ([input (car in_string)])
(set! current_state (filter (lambda (v)
(match v
[(list (== current_state) (== input) _) #t]
[_ #f]))
delta_fn)))
(writeln current_state)]
;(transition current_state in_string delta_fn)]
)
)
So at the moment, if you run this script and the type: (transition current_state in_string delta_fn), you will get the following output:
> (transition current_state in_string delta_fn)
0
("a" "b" "b" "b")
((0 "a" 0) (0 "b" 1) (1 "a" 0) (1 "b" 1))
((0 "a" 0))
That last line: ((0 "a" 0)) is a result of the (writeln current_state) command after the lambda function runs to find its match in the delta_fn list. I thought I could just type (cdr (cdr current_state)) right there to get the third item in that output, but ((0 "a" 0)) is not a list and I can't operate on it like a list.
So my question is: what is ((0 "a" 0))? Why is current_state set to that instead of '(0 "a" 0)?
Any help would be greatly appreciate, please know that I am very new to functional programming in general, so use small words =P
Solution!
(define (transition current_state in_string delta_fn)
(cond
[(empty? in_string) (writeln current_state)]
[else
(let ([input (car in_string)])
(set! filtered_delta_fn (filter (lambda (v)
(match v
[(list (== current_state) (== input) _) #t]
[_ #f]))
delta_fn)))
(set! next_state (car (cdr (cdr (car filtered_delta_fn)))))
(transition next_state (cdr in_string) delta_fn)]
)
)
You are reusing the variable current_state. Don't do that!
First it was 0, the initial state.
Then you change it to hold a totally different value, the result of filter operation. Instead, use some temporary variable for that, so current_state is not changed yet.
Now, filter returns that value you ask about, ((0 "a" 0)), because of all the entries in the delta_fn it kept the one matching your criterion, the list (0 "a" 0). So the filtered list holds one matching entry in it.
To find your next state from it, simply call
(set! next_state (car (cdr (cdr (car filtered_delta_fn)))))
; (0 "a" 0)
; ("a" 0)
; (0)
; 0
where filtered_delta_fn will be the temporary variable mentioned above.
Then, the recursive call will now be
(transition next_state in_string delta_fn)
You could use current_state in place of next_state, but that's just messy. Much better to have all your variables meaningful, with proper values corresponding to their meaning. Otherwise, it is easy to quickly get lost in all the complex confusion.
Also, the use of set! is usually frowned upon. In Scheme we usually declare a new variable to be used henceforth, like
(let ((next_state (car (cdr ..... ))))
; recursive call .....

Common Lisp let function

I'm just starting to program in Common Lisp and going back through programs that I coded during some of my previous classes to learn and I am having trouble understanding the problem in my code.
(defun input-1 ()
(defvar *message* (read-line))
(defvar *a-value* (parse-integer(read-line)))
(defvar *b-value* (parse-integer(read-line))))
(defun alphabet (list " " "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m"
"n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"))
(defun alphabet-num (list 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29))
;(defun inverse (value)
; (let ((x 0))
; (loop while (< x 29)
; (print x))))
(defun inverse (value)
(dotimes (x 28)
(when (equal (mod (* x value) 29) 1)
(return-from inverse x))))
(defun get-int (string)
(getf (position string alphabet) alphabet-num))
(defun get-string (int)
(getf (position int alphabet) alphabet))
(defun cipher-calc (character)
(let ((c-int (get-int character))
(f-char ""))
(setf c-int (* *a-value* (- c-int *b-value*)))
(setf f-char (get-string (mod (abs c-int) 29)))))
However, I am getting this error
; in: DEFUN CIPHER-CALC
; (* *A-VALUE* (- C-INT *B-VALUE*))
;
; caught WARNING:
; undefined variable: *A-VALUE*
; (- C-INT *B-VALUE*)
;
; caught WARNING:
; undefined variable: *B-VALUE*
; (GET-INT CHARACTER)
;
; caught STYLE-WARNING:
; undefined function: GET-INT
; (GET-STRING (MOD (ABS C-INT) 29))
;
; caught STYLE-WARNING:
; undefined function: GET-STRING
;
; compilation unit finished
; Undefined functions:
; GET-INT GET-STRING
; Undefined variables:
; *A-VALUE* *B-VALUE*
; caught 2 WARNING conditions
; caught 2 STYLE-WARNING conditions
I find it difficult to believe that you cannot call a function inside of a let block, so I'm assuming I am making an error. Any other tips on my code would be welcome.
Your code:
(defun input-1 ()
(defvar *message* (read-line))
(defvar *a-value* (parse-integer(read-line)))
(defvar *b-value* (parse-integer(read-line))))
DEFVAR is supposed to be used on the top-level and not inside a function. In this case the variables will be defined when the function runs. But when you just compile, evaluate or load such a function, the variable is not defined. Thus the compiler will later warn that in your code these variables are undefined.
When DEFVAR is used at top-level, then Lisp will recognize that there are variable definitions.
(defvar *message*)
(defvar *a-value*)
(defvar *b-value*))
(defun input-1 ()
(setf *message* (read-line))
(setf *a-value* (parse-integer (read-line)))
(setf *b-value* (parse-integer (read-line))))
defvar doesn't do what you think it does. It ensures the variable exist and if it happens to no exist it binds it to the second argument. Thus:
(defvar *test* 5)
(defvar *test* 10) ; already exist, has no effect
*test* ; ==> 5
What you can do is define them like this on the top of your file and use setf in your function:
(defvar *message*)
(defun input-1 ()
(setf *message* (read-line))
...)
After all setting is what you are doing. You are mixing functions and variables with alphabet. Here you could use defparameter. It is like defvar but it always overwrite when you load the file:
(defparameter *alphabet* (list " " "a" "b" ...))

Achieve (format nil ...) with princ

Here's the behavior of a few format and princ calls:
(format nil "a")
"a"
CL-USER>
(format t "a")
a
NIL
CL-USER>
(princ "a" nil)
a
"a"
CL-USER>
(princ "a" t)
a
"a"
CL-USER>
I would have thought that the (princ "a" nil) call would have returned "a", but not printed "a" to stdout, but it still prints "a" to stdout. Also I'm not sure why there's not a difference between the first and second princ calls.
I tried browsing the hyperspec, but I can't find the information I need.
I assume my misunderstanding is because nil and t are not streams, but format translates them to the return stream (whatever that is) and stdout. If that's the case, how can I get a (format nil ...) effect with (princ ... ?)
The function FORMAT is different from other output functions in that it accepts NIL to mean "return the output in a string instead of writing it". The general solution as suggested by Rainer is to use WITH-OUTPUT-TO-STRING.
Usually, there are special versions of the print functions that return the output as a string instead. In this particular case, what you want is the function PRINC-TO-STRING which does the same thing as PRINC but returns a string.
CL-USER 25 > (with-output-to-string (stream)
(princ "a" stream))
"a"

Adding values from a tab delimited string to a plist

How would I go about adding values from a tab delimited string to a plist?
(dolist (x *lines*)
(cl-ppcre:split "\t" x))
*lines* is a list of tab delimited strings loaded from a file, and I want to make a plist of the form
(:a value1 :b value2 :c value 3)
Thanks!
(let ((line '("foo" "bar" "baz")))
(loop for item in line and key in '(:a :b :c) collect key collect item))
=> (:A "foo" :B "bar" :C "baz")
(mapcan 'list '(:a :b :c) '("foo" "bar" "baz"))
=> (:A "foo" :B "bar" :C "baz")
You should read the lines from the file, CL-PPCRE:SPLIT them to get the list, and step through this list:
(loop
for (key value) on (cl-ppcre:split " " "a value1 b value2 c value3") by #'cddr
appending (list (intern (string-upcase key) (find-package :keyword))
value))

Resources