Mitchell
Mitchell

Reputation: 15

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.

Upvotes: 0

Views: 1315

Answers (2)

Sylwester
Sylwester

Reputation: 48745

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

Upvotes: 1

Rainer Joswig
Rainer Joswig

Reputation: 139251

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

Upvotes: 1

Related Questions