Finite State Machine code

General Tech Learning Aids/Tools 2 years ago

0 2 0 0 0 tuteeHUB earn credit +10 pts

5 Star Rating 1 Rating

Posted on 16 Aug 2022, this text provides information on Learning Aids/Tools related to General Tech. Please note that while accuracy is prioritized, the data presented might not be entirely correct or up-to-date. This information is offered for general knowledge and informational purposes only, and should not be considered as a substitute for professional advice.

Take Quiz To Earn Credits!

Turn Your Knowledge into Earnings.

tuteehub_quiz

Answers (2)

Post Answer
profilepic.png
manpreet Tuteehub forum best answer Best Answer 2 years ago

 

I have been making this FSM today. However, as this is probably the biggest practical program I have ever written in CL, I don't know if there are some things that could be improved, or if using a closure is the best thing here.

Any feedback is appreciated.

;;; States: -- EnterMineAndDigForNugget 
;;;         -- QuenchThirst
;;;         -- GoHomeAndSleepTillRested
;;;         -- VisitBankAndDepositGold

(defmacro while (test &rest body)
    `(do ()
             ((not ,test))
         ,@body))

(defmacro enter (state)
    `(setf state ,state))

(defun make-miner ()
    (let ((wealth 0)
                (thirst 0)
                (rested 0)
                (state 'EnterMineAndDigForNugget))
        (list 
         (defun EnterMineAndDigForNugget ()
                                                                                ;   (setf location 'mine)
             (format t "~&Diggin' up gold!")
             (incf wealth)
             (incf thirst)
             (cond ((>= thirst 7) (enter 'QuenchThirst))
                         (t (enter 'VisitBankAndDepositGold))))
         (defun QuenchThirst () 
             (format t "~&Drinkin' old good whiskey")
             (setf thirst 0)
             (enter 'EnterMineAndDigForNugget))
         (defun VisitBankAndDepositGold ()
             (format t "~&All this gold ought to be stored somewhere!")
             (incf wealth)
             (cond ((>= wealth 5) (progn 
                                                            (format t "~&Too much gold for today, let's sleep!")
                                                            (enter 'GoHomeAndSleepTillRested)
                                                            (setf wealth 0)))
                         (t (EnterMineAndDigForNugget))))
         (defun GoHomeAndSleepTillRested ()
             (while (<= rested 3)
                 (format t "~&Sleepin'")
                 (incf rested))
             (enter 'EnterMineAndDigForNugget)
             (setf rested 0))
         (defun controller ()
             (dotimes (n 30)
                 (cond ((equal state 'QuenchThirst) (QuenchThirst))
                             ((equal state 'VisitBankAndDepositGold) (VisitBankAndDepositGold))
                             ((equal state 'GoHomeAndSleepTillRested) (GoHomeAndSleepTillRested))
                             ((equal state 'EnterMineAndDigForNugget) (EnterMineAndDigForNugget))))))))

EDIT

I have applied all the suggested changes but for the flet/labels one. Everything worked fine until I changed the one of "set the state to the next function". Now, the macro enter doesn't seem to be ever called.

This is the current state of the code, with the required code to make it work


                                                
                                                
0 views
0 shares
profilepic.png
manpreet 2 years ago

DEFUN

The most basic mistake in your code is that DEFUN is not correct for nested functions. DEFUN is a top-level macro, defining a top-level function and should be used in top-level forms.

Nested functions are defined in Common Lisp with FLET and LABELSLABELS is used for recursive sub-functions.

Naming

Symbols like FooBarBaz are not use in Common Lisp. By default Common Lisp upcases all names internally, so the case information gets lost.

Usually we write foo-bar-baz.

Checking symbols

Use CASE (or ECASE) instead of (cond ((equal foo 'bar) ...)).

Architecture

Usually I would write that piece of code using CLOS, the Common Lisp Object System.

In a more functional style I would propose the following:

  • use LABELS for the local procedures.

  • set the state to the next function. A function is written as (function my-function) or #'my-function.

  • the controller just calls the next function from the state variable. It is not necessary to list all cases.


0 views   0 shares

No matter what stage you're at in your education or career, TuteeHub will help you reach the next level that you're aiming for. Simply,Choose a subject/topic and get started in self-paced practice sessions to improve your knowledge and scores.