Usually when I find myself fighting to prove a point it's usually becuase it's a loosing battle and my ego just won't let go.
But let's assume you actually might be interesting seeing why a simple lisp like scripting language might be intesting.
I wanted to change the behavior of a display terminal. I wanted it to have a list of times (hours in the day) and different behaviors.
- homework time = m-f, 3-5pm
- blank display, all ways, 10pm - 6am
I cranked out some quick scheme code in 15 minutes to do this. Basically I made a list of times with functions to call to check if the time is now and a function to be called when the time starts and stops.
I don't think I could have done that as generally in C, C++ or /bin/sh in the same time. I could have done something pretty specific in /bin/sh but then it would be a pain and lots of duplicated text if I wanted to add another time, event. C or C++ would have required some debugging time and more pain dealing with lists, etc... (assuming no STL++, thank you very much)
going backwards (or starting at the top), I first defined the times:
;; (define (time-init) (add-sleep-time (config-get 'sleep-hours)) (add-homework-time (config-get 'homework-hours)) t)
Note that config-get returns a "dotted pair" of begin & end times, i.e. "(10 . 6)" or "(3 . 5)". In lisp a dotted pair is between an atom (like a number) and a list (often a list of atoms).
Then I define how to add times to the list:
;; add time, any day (define (add-sleep-time hour-pair) (add-special-time 'hour-check hour-pair 'its-sleep-time '*sleeping*)) ;; add time, but weekday only (define (add-homework-time hour-pair) (add-special-time 'hour-check-weekday hour-pair 'its-homework-time '*homework*)) ;; make list of special times with check & action functions (define (add-special-time check-function hour-pair action-function state-var) (set! *special-times* (nconc *special-times* (cons (list check-function hour-pair action-function state-var)))))
Note that *sleeping* is a globle variable which gets set. It's quoted so it won't be evaluated to it's value (we just want it's name). hour-check is the function to call to check the time. its-sleep-time is the function to call when the time is entered.
Then I define the functions to check the time:
;; (define (weekday) (let* ((ltime (localtime)) (wday (cdr (assoc 'wday ltime)))) ;; 0=sunday, 6=saturday (and (> wday 0) (< wday 6)))) ;; (define (hour-check-weekday time-pair) (and (weekday) (hour-check time-pair)))
I then spent 10 minutes debugging it (interactively) and then installed it in the larger body of code. Viola. New behavior.
And, or completeness, here the other functions:
;; (define (check-time) (let ((st *special-times*)) (while st (let* ((item (car st)) (func (eval (first item))) (data (second item)) (action (eval (third item))) (state-var (fourth item)) (state (eval state-var))) (printf "item % % data %n" item state data) ;; enter (and (not state) (func data) (event-time t action item) (set-symbol-value! state-var t)) ;; exit (and state (not (func data)) (event-time nil action item) (set-symbol-value! state-var nil))) (set! st (cdr st))))) ;; (define (hour-check time-pair) (let* ((ltime (localtime)) (hour (cdr (assoc 'hour ltime))) (mins (cdr (assoc 'min ltime))) (min (car time-pair)) (max (cdr time-pair))) (printf "hour-check % % %n" hour min max) ;; if span crosses midnight (if (> min max) (or (>= hour min) (< hour max)) ;; normal span (and (>= hour min) (< hour max)))))
With any luck this is mildly interesting. And, maybe it shows how simple it is to add complex functionalty. Or maybe it doesn't. But it was fun to do and I didn't get all bolluxed up with bad pointers or overflowing arrays or gdb. To me this is a fairly compact representation of a simple behavior and very handy on a small embedded system.