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" ...))
Related
I'm building an alphametic solver, and I'd like to make a macro that substitutes numbers into a symbol template.
Here is a self-contained example:
(defparameter *symbol-positions* '(#\H #\T #\S #\R #\A #\U #\E #\O #\W #\N))
(defmacro word-to-number (symbols lst)
`(tonumber (list ,#(loop for symbol in symbols
when (not (eql symbol #\ ))
collect `(nth ,(position symbol *symbol-positions*) ,lst )))))
(defparameter num '(0 1 2 3 4 5 6 7 8 9))
(defparameter east '(#\ #\E #\A #\S #\T))
The following call works:
(word-to-number (#\ #\E #\A #\S #\T) num)
But this one doesn't:
(word-to-number east num) ;=> The value EAST is not of type LIST
Is there a way I can modify the macro to take a variable for the SYMBOLS parameter? ,symbols doesn't work, and neither does `(,#symbols)
When you do:
(word-to-number east num)
The macro expander gets called with the arguments being east and num. They won't be lists and number for you macro. Only for the resulting code will they be evaluated in a contex which yields values.
A macro is syntax transformation. eg.
(cond (p1 c1)
(p2 c2)
(t a))
; ==
(if p1
c1
(if p2
c2
a))
It is regardless if p1 is (< a b) or my-boolean-value. A macro just places the expressions there without having to know what a, b or my-boolean-value is.
So tell me.. How should the expansion look with (word-to-number east num)? Perhaps it shouldn't be a macro at all? eg.
(defun word-to-number (symbols lst)
(tonumber (loop :for symbol :in symbols
:when (not (eql symbol #\ ))
:collect (nth (position symbol *symbol-positions*) lst))))
UPDATE
(defmacro word-to-number (symbols lst)
`(tonumber (loop :for symbol :in ,symbols
:with clst := ,lst
:when (not (eql symbol #\ ))
:collect (nth (position symbol *symbol-positions*) clst))))
You might notice that I'm storing lst in a variable clst and I do it after evaluating symbols. The reason is that when you expect arguments to be evaluated you expect them to be evaluated in order and only once unless repeated evaluation is a feature of the macro like loop does. Eg. this should only print "Oh, happy day" once:
(word-to-number (progn (princ "Oh") east) (progn (princ ", happy day!") num))
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 .....
Define the function 'occ' that takes a list L and a symbol A and counts the occurance of symbol A in L.
Example:
(occ '(((s) o ) d) 'f) --> 0
What i have gotten so far:
(defun occ(list a)
(setq counter 0)
;Checks if the given list is has an nested list
(if (consp list)
; Breaking the list down atom by atom and recursing
(or (occ a (car list))
(occ a (cdr list)))
; checks if symbols are the same
(if(eq a list)
(setq counter(1+ counter)))))
However My output keep saying Nil instead of displaying the counter value.
I cannot use any higher-functions of LISP.
First of all, don't use setq for variable initialization inside yout function, use let. Second, let's look why you doing it wrong, your code:
(defun occ(list a)
(setq counter 0) ;; You always setting counter to 0 on new
;; level of recursion
(if (consp list)
(or (occ a (car list)) ;; You reversed arguments order?
(occ a (cdr list))) ;; according to your definition it must be
;; (occ (car list) a)
(if(eq a list)
(setq counter(1+ counter)))))
Anyway, you don't need any counter variables to do what you want.
Right function may look like this (i changed arguments order becaus it looks better for me to find SYMBOL in LIST):
(defun occ (sym nested-list)
(cond
((consp nested-list)
(+ (occ sym (car nested-list)) (occ sym (cdr nested-list))))
((eq sym nested-list) 1)
(t 0)))
CL-USER> (occ 'x '(((s) o ((f ()) f)) d))
0
CL-USER> (occ 'f '(((s) o ((f (x (((f))))) f)) d f))
4
If you feed your definition to SBCL:
; in: DEFUN OCC
; (SETQ COUNTER 0)
;
; caught WARNING:
; undefined variable: COUNTER
;
; compilation unit finished
; Undefined variable:
; COUNTER
; caught 1 WARNING condition
So you are modifying a global undefined variable counter. When do the function return? Well, or will return the very first non nil return from recursion with car or cdr. What returns values? Well when it's not a cons it will evaluate to the intermediate value of a incf of counter when the symbol matches or nil when it doesn't.
Try doing it like this:
(defun occ (list a &optional (counter 0))
(cond ((equal list a) (1+ counter))
((atom list) counter)
(t (occ (cdr list)
a
(occ (car list)
a
counter)))))
counter is an optional accumulator that you use to hold the values. Since it's passed it isn't shared between the recursive calls but replaced with the updated value at each call making it functional and easy to follow. When you need to search both car and cdr you recurse car with the counter of this stage and the returning value will be used as the counter in the cdr. For lists of atom this will be tail recursive if the implementation supports it. This supports finding symbols as tails of lists. eg. (occ '((x . x) . x) 'x) ; ==> 3 If you are sure you have no dotted list (every list is nil terminated) you can use the loop macro:
(defun occ (list a)
(loop :for e :in list
:counting (equal e a) :into count
:if (consp e)
:summing (occ e a) :into sum
:finally (return (+ count sum))))
;; tests
(occ '(x (x x (x (x ) x)) y z) 'y) ; ==> 1
(occ '(x (x x (x (x ) x)) y z) 'x) ; ==> 6
(occ '((x . x) . x) 'x) ; ERROR like "A proper list must not end with X".
By "artificial", I mean one created from a string using intern or make-symbol.
I have a section of my code that declares up to 49 global variables:
(defparameter *CHAR-COUNT-1-1* (make-hash-table))
...
(defparameter *CHAR-COUNT-1-7* (make-hash-table))
...
(defparameter *CHAR-COUNT-7-7* (make-hash-table))
I thought, instead, I could create a function to do all that:
(loop for n from 1 to 7 do
(loop for i from 1 to 7 do
(defparameter (symbol-value (intern (concatenate 'string "*CHAR-COUNT-" (write-to-string n) "-" (write-to-string i) "*")))
(make-hash-table :test 'equalp))))
But get the error(sbcl):
unhandled SIMPLE-ERROR in thread #<SB-THREAD:THREAD "main thread" RUNNING
{1002978EE3}>:
Can't declare a non-symbol as SPECIAL: (SYMBOL-VALUE
(INTERN
(CONCATENATE 'STRING "*CHAR-COUNT-"
(WRITE-TO-STRING N) "-"
(WRITE-TO-STRING I)
"*")))
What is the correct way to do this?
Defparameter is a macro, not a function. That means that it defines a special syntax. The defparameter form needs to have a symbol as its second argument, but you're providing the list:
(symbol-value (intern (concatenate 'string "*CHAR-COUNT-" (write-to-string n) "-" (write-to-string i) "*")))
What you want is a form like
(progn
(defparameter *foo-1-1* (make-hash-table ...))
...
(defparameter *foo-n-n* (make-hash-table ...)))
You seem familiar enough with loop and creating the symbols to create that list; just change
(loop … do (loop … do (defparameter …)))
to
`(progn
,#(loop … nconcing
(loop … collecting
`(defparameter ,(intern …) …))))
and you can get the form you need. Then it's just a matter of putting it all into a macro
(defmacro … (…)
`(progn
,#(loop … nconcing
(loop … collecting
`(defparameter ,(intern …) …)))))
and calling the macro.
One of "use a macro that returns a PROGN with DEFPARAMETER stanzas" or "use PROCLAIM, it is a function, not a macro".
The correct way is to use a proper data structure instead of encoding dimensions in symbol names. Do you really want to calculate and encode symbol names any time you want to access the correct table?
(defparameter *char-counts* (make-array '(7 7)))
(dotimes (i 49) ; or (reduce #'* (array-dimensions *char-counts*))
(setf (row-major-aref *char-counts* i) (make-hash-table)))
Now you can access the array of tables just with the indices (x and y in this example):
(gethash (aref *char-counts* x y) :foo)
I am trying to implement a macro which expands a unlimited list of triplet-arguments into lambda-function to check an argument (object).
e.g.
(where >= amount 5 equalp name "george")
=>
#'(lambda (arg)
(and
(>= (amount arg) 5)
(equalp (name arg) "george")))
I got quite close with this macrodefinition:
(defmacro where (&rest list-of-argument-triplets )
`#'(lambda (arg)
(and
,(do ( (counter 0 (+ counter 3)) (liste (list)))
( (>= counter (list-length list.of-argument-triplets)) liste)
(push `( ,(nth counter list-of-argument-triplets)
( ,(nth (+ counter 1) list-of-argument-triplets) arg)
,(nth (+ counter 2) list-of-argument-triplets)
liste)))))
but this expands to
#'(lambda (arg)
(and ((>= (amount arg) 5)
(equalp (name arg) "george"))))
which is one parentheses after the "and" too much. As a conclusion I would have to use an # in front of the result-form, but then the "#list" is treated
as if it is an parameter-name, and therefore I get an no-value error, instead of an expanded list.
*** - RETURN-FROM: variable #LISTE has no value
How can I fix that?
Code smell: you use NTH to access elements of a list.
I would first define a helper function, which makes out of the flat list a list of three element lists:
(defun triplets (list)
(loop while list
collect (list (pop list)
(pop list)
(pop list))))
CL-USER 1 > (triplets '(a b c d e f g h i))
((A B C) (D E F) (G H I))
The macro is then slightly simpler to write:
(defmacro where (&rest flat-triplets)
`#'(lambda (arg)
(and
,#(mapcar (lambda (triplet)
(destructuring-bind (fn accessor item)
triplet
`(,fn (,accessor arg) ,item)))
(triplets flat-triplets))))
CL-USER 2 > (macroexpand-1 '(where >= amount 5 equalp name "george"))
(FUNCTION (LAMBDA (ARG) (AND (>= (AMOUNT ARG) 5) (EQUALP (NAME ARG) "george"))))
T