From: steve on
Can anyone tell me why the following line generates an error (but still
prints the correct output!)? It's a simple finite automata simulator;
str is a list of integers (ASCII values); and the following line occurs
when the recursive FA function encounters a character from outside of
the alphabet {a, b} (or {97, 98} if you prefer):

(princ (format "%s unrecognized input\nrejected\n" (char-to-string (car
str))) lisp-out))

Wrong type argument: integer-or-marker-p, "y unrecognized
input^Jrejected^J"

Here is the whole program if necessary:

;Assignment: Finite Automata Simulator

(cond ((get-buffer "*lisp-out*") (kill-buffer "*lisp-out*")))
(setq lisp-out (get-buffer-create "*lisp-out*"))

(defun FA (str)
(cond
((null str) state)
((equal (car str) 97)
(cond
((equal state 1) (setq state 3))
((equal state 2) (setq state 4))
((equal state 3) (setq state 4))
((equal state 4) (setq state 5))
((equal state 5) (setq state 2))
)
(princ (format "a - > State %d\n" state) lisp-out)
(setq i (+ i 1))
(FA (cdr str))
)
((equal (car str) 98)
(cond
((equal state 1) (setq state 5))
((equal state 2) (setq state 1))
((equal state 3) (setq state 2))
((equal state 4) (setq state 4))
((equal state 5) (setq state 3))
)
(princ (format "b - > State %d\n" state) lisp-out)
(setq i (+ i 1))
(FA (cdr str))
)
(t (princ (format "%s unrecognized input\nrejected\n" (char-to-string
(car str))) lisp-out))
)
)

(defun accept (state)
(cond
((equal (% state 2) 1) 't)
(t 'f)
)
)

(setq keepgoing 't)
(while keepgoing
(setq s (read-string "String: "))
(princ (format "String: %s\n" s) lisp-out)
(setq s (mapcar 'identity s))
(cond
((equal s '(101 110 100))
(princ (format "bye\n") lisp-out)
(setq keepgoing nil)
)
(t (princ (format "Start State 1\n") lisp-out)
(setq state 1)
(setq i 0)
(cond
((accept (FA s)) (princ (format "accepted\n") lisp-out))
(t (princ (format "rejected\n") lisp-out))
)
)
)
)

From: steve on
....please ignore the final closing paren on the line of code in
question...if you look at the full code you can see it has a matching
open paren: (t (princ...))

From: Barry Margolin on
In article <1140184295.965774.229200(a)g44g2000cwa.googlegroups.com>,
steve(a)stevedurkin.net wrote:

> Can anyone tell me why the following line generates an error (but still
> prints the correct output!)? It's a simple finite automata simulator;
> str is a list of integers (ASCII values); and the following line occurs
> when the recursive FA function encounters a character from outside of
> the alphabet {a, b} (or {97, 98} if you prefer):
>
> (princ (format "%s unrecognized input\nrejected\n" (char-to-string (car
> str))) lisp-out))
>
> Wrong type argument: integer-or-marker-p, "y unrecognized
> input^Jrejected^J"

princ returns its first argument after printing it, so FA is returning
the error message. Your accept function passes the return value to %,
but this isn't valid for strings. So either you need better error
checking of the return value, or you need to ensure that FA always
returns a state, even in the error case.

>
> Here is the whole program if necessary:
>
> ;Assignment: Finite Automata Simulator
>
> (cond ((get-buffer "*lisp-out*") (kill-buffer "*lisp-out*")))
> (setq lisp-out (get-buffer-create "*lisp-out*"))
>
> (defun FA (str)
> (cond
> ((null str) state)
> ((equal (car str) 97)
> (cond
> ((equal state 1) (setq state 3))
> ((equal state 2) (setq state 4))
> ((equal state 3) (setq state 4))
> ((equal state 4) (setq state 5))
> ((equal state 5) (setq state 2))
> )
> (princ (format "a - > State %d\n" state) lisp-out)
> (setq i (+ i 1))
> (FA (cdr str))
> )
> ((equal (car str) 98)
> (cond
> ((equal state 1) (setq state 5))
> ((equal state 2) (setq state 1))
> ((equal state 3) (setq state 2))
> ((equal state 4) (setq state 4))
> ((equal state 5) (setq state 3))
> )
> (princ (format "b - > State %d\n" state) lisp-out)
> (setq i (+ i 1))
> (FA (cdr str))
> )
> (t (princ (format "%s unrecognized input\nrejected\n" (char-to-string
> (car str))) lisp-out))
> )
> )
>
> (defun accept (state)
> (cond
> ((equal (% state 2) 1) 't)
> (t 'f)
> )
> )
>
> (setq keepgoing 't)
> (while keepgoing
> (setq s (read-string "String: "))
> (princ (format "String: %s\n" s) lisp-out)
> (setq s (mapcar 'identity s))
> (cond
> ((equal s '(101 110 100))
> (princ (format "bye\n") lisp-out)
> (setq keepgoing nil)
> )
> (t (princ (format "Start State 1\n") lisp-out)
> (setq state 1)
> (setq i 0)
> (cond
> ((accept (FA s)) (princ (format "accepted\n") lisp-out))
> (t (princ (format "rejected\n") lisp-out))
> )
> )
> )
> )

--
Barry Margolin, barmar(a)alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Alexander Schmolck on
steve(a)stevedurkin.net writes:

> Here is the whole program if necessary:

You already got an answer to your specific question, some other remarks (if
this is just a one-of excercise, ignore what you think you don't need):

- don't put ) on empty lines. It's considered bad style and if you understand
how to use emacs properly you don't need to pay visual attention to those
parens.

- always declare global variables with defvar and local ones with let

- 't is the same as t (the boolean true). I assume that instead of 'f you want
nil (the boolean false and also the empty list). Then your accept function
just becomes (defun accept (state)
(equal (% state 2) 1)) ; (= (% state 2) 1) is more idiomatic

- for two-armed conditionals you could also use if

> (defun FA (str)
> (cond
> ((null str) state)
> ((equal (car str) 97)

You can also write (equal (car str) ?a).

> (cond
> ((equal state 1) (setq state 3))
> ((equal state 2) (setq state 4))
> ((equal state 3) (setq state 4))
> ((equal state 4) (setq state 5))
> ((equal state 5) (setq state 2))
> )

If you put a (require 'cl) at the top of your file, you could replace the cond
with:

(setq state (ecase state (1 3) (2 4) (3 4) (4 5) (5 2)))

It's shorter, gives an error if state is not in 1..4 (if you don't want that
use case instead) and should also be more efficient (not that it matters
here).

Similarly you could then also use (incf i) instead of (setq i (+ i 1)).

'as
From: steve on
thanks for all the info...it is a one-of exercise, but i still
appreciate all the information and advice.