1
votes

I'm pretty new to racket and I'm trying to make a finite state machine for a project. here's what I have so far.

#lang racket

(define (test rules cs pass lst)
  (if (eq? (length lst) 0)
      (if (member cs pass)
          (write 'passed)
          (write 'failed))
      (test rules (next rules cs (car lst)) (cdr lst))))

(define (next rules cs input)
  (if (eq? cs (car (car rules)))
      (if (eq? input (car(cdr(car rules))))
          (car(cdr(cdr(car rules))))
          ((next (cdr rules) cs input)))
      (next (cdr rules) cs input)))

then I input

(define rules '('(0 a 0) '(0 b 1) '(1 a 0) '(1 b 1)))
(define pass '(1))
(test rules 0 pass '(a b a b))

and for a reason that I cannot figure out, I get this error on the next function. It acts as though rules is an empty list, which I'm pretty sure it's not. Anyway if anyone could tell me why it's doing that it would really help.

Thanks!

EDIT1

Thanks so much for the help guys. It's really helping. The code is working entirely until the end, but now it throws an error at the end of my code if I test multiple lists with testmany.

(define (testmany rules cs pass lst)(if (eq? (length lst) 0)
                                        (write 'done)     
        ((test rules cs pass (car lst))                         
         (testmany rules cs pass (cdr lst)))))

(define (test rules cs pass lst) (if (eq? (length lst) 0)
        (if (member cs pass)
            (write 'accepted.....)
            (write 'rejected.....))
        (test rules (next rules cs (car lst)) pass (cdr lst))))

(define (next rules cs input) (if (eq? cs (car (car rules)))
         (if (eq? input (car(cdr(car rules))))
             (car(cdr(cdr(car rules))))
             (next (cdr rules) cs input))
         (next (cdr rules) cs input)))

The code doesn't seem to know when to stop the recursion of the testmany function. When the list is empty, it prints done, but then continues the next part as if the list still had elements, throwing this error. If anyone knows why it is throwing this error please let me know. Thanks!

1
For when you (define rules ...), see What is the difference between quote and list? and its answers. When in doubt, just use list, it's simpler.Alex Knauth
((next...) means that the next function will return a function that you immediately call. If the returned value is anything else you'll get a runtime error from apply. '('(0 a 0) ...) evaluates to ((quote (0 a 0)) ...) since only the outer quote is code, the rest became data.Sylwester
In this scenario when (member cs pass) evaluates to a list there will be a crash. To fix this you would need to put (boolean? (member cs pass and switch the if statement arguments to 'failed then 'passed as to keep it consistent with this example. The last line of the (test ...) function has too less arguements. test requires 4 and only 3 has been passedMartin Watson

1 Answers

0
votes

You forgot the begin:

(define (testmany rules cs pass lst) (if (eq? (length lst) 0)
                                         (write 'done)     
        (begin
       ; ^^^^^ here
         (test rules cs pass (car lst))                         
         (testmany rules cs pass (cdr lst)))))

Without it, the return value of (test rules cs pass (car lst)) is attempted to be used as a function; but it is #<void>, the result of (write ....) form, which is the last one evaluated (more like, executed) by your test function.

By the way, #<void> is not an empty list; it's more like a non-value.

edit: the reason it does recurse to the end (without the begin) is that to apply a function foo in (foo val) to a value val, both expressions are evaluated first.

It is only after the evaluation of val, i.e. (testmany ...), finishes fully that the error is discovered that the value of foo, i.e. (test ...) expression, is not in fact a function, and can not be applied.