circular-sclist/recurring-event [ Classes ]

[ Top ] [ circular-sclist ] [ Classes ]

NAME

 rthm-chain

 File:             recurring-event.lsp

 Class Hierarchy:  named-object -> linked-named-object -> sclist -> 
                   circular-sclist -> recurring-event

 Version:          1.0.12

 Project:          slippery chicken (algorithmic composition)

 Purpose:          class used in rthm-chain
                   This class allows for the periodic/cyclic return of given
                   data.  It is intended for situations where you want to
                   do/collect something every several events, but the cycle
                   period changes.  E.g. (the data slot is) something like
                   '((2 3) (3 2) (5 3) (8 2)) which means every two events
                   three times, then every 3 events twice, every 5 events
                   thrice etc.

                   If you want to return specific data on these cycle
                   points, provide it in the return-data slot, with the
                   indices into this data in the return-data-cycle slot.

                   simple example, without return-data
                   (let* ((re (make-re '((2 3) (3 2) (5 3) (8 2))
                                       :return-data nil 
                                       :return-data-cycle nil)))
                     (loop repeat 100 collect (on-it re)))

                   => (NIL NIL T NIL T NIL T NIL NIL T NIL NIL T NIL NIL NIL
                       NIL T NIL NIL NIL NIL T NIL NIL NIL NIL T NIL NIL NIL
                       NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL NIL T NIL T
                       NIL T NIL T NIL NIL T NIL NIL T NIL NIL NIL NIL T NIL
                       NIL NIL NIL T NIL NIL NIL NIL T NIL NIL NIL NIL NIL
                       NIL NIL T NIL NIL NIL NIL NIL NIL NIL T NIL T NIL T
                       NIL T NIL NIL T NIL NIL T NIL)
 
                   (let* ((re (make-re '((2 3) (3 2) (5 3) (8 2)) 
                                       ;; the data about to be collected 
                                       :return-data '(a b c d)
                                       ;; the indices into the data; this
                                       ;; means we'll return A (nth 0)
                                       ;; thrice, D (nth 3) twice, C once,
                                       ;; and B 5x
                                       :return-data-cycle 
                                       '((0 3) (3 2) (2 1) (1 5))))) 
                     (loop repeat 100 collect (get-it re)))

                   => (NIL NIL A NIL A NIL A NIL NIL D NIL NIL D NIL NIL NIL
                       NIL C NIL NIL NIL NIL B NIL NIL NIL NIL B NIL NIL NIL
                       NIL NIL NIL NIL B NIL NIL NIL NIL NIL NIL NIL B NIL B
                       NIL A NIL A NIL NIL A NIL NIL D NIL NIL NIL NIL D NIL
                       NIL NIL NIL C NIL NIL NIL NIL B NIL NIL NIL NIL NIL
                       NIL NIL B NIL NIL NIL NIL NIL NIL NIL B NIL B NIL B
                       NIL A NIL NIL A NIL NIL A NIL)

 Author:           Michael Edwards: m@michael-edwards.org

 Creation date:    4th February 2010

 $$ Last modified:  10:37:45 Wed Jun  7 2023 CEST

 SVN ID: $Id$

recurring-event/get-it [ Methods ]

[ Top ] [ recurring-event ] [ Methods ]

DESCRIPTION

 Get the next element from the return-data. This method is most effective
 when called repeatedly (e.g. within a loop) when the return-data and
 return-data-cycle slots have been set. In those cases the return-data-cycle
 element will be used as look-up into return-data. If no return-data has
 been specified, then the element itself will be returned.

ARGUMENTS

 - A recurring-event object.

RETURN VALUE

 Data from the return-data slot (or the return-data-cycle element) when
 we're on a boundary, otherwise NIL. 

EXAMPLE

;;; Used together with return-data
(let ((re (make-re '((2 3) (3 2) (5 3) (8 2)) 
                   :return-data '(a b c d)
                   :return-data-cycle '((0 3) (3 2) (2 1) (1 5)))))
  (loop repeat 50 collect (get-it re)))

=> (NIL NIL A NIL A NIL A NIL NIL D NIL NIL D NIL NIL NIL NIL C NIL NIL NIL NIL
    B NIL NIL NIL NIL B NIL NIL NIL NIL NIL NIL NIL B NIL NIL NIL NIL NIL NIL
    NIL B NIL B NIL A NIL A)

;;; Used without return-data
(let ((re (make-re '((2 3) (3 2) (5 3) (8 2)) 
                   :return-data-cycle '((0 3) (3 2) (2 1) (1 5)))))
  (loop repeat 50 collect (get-it re)))

=> (NIL NIL 0 NIL 0 NIL 0 NIL NIL 3 NIL NIL 3 NIL NIL NIL NIL 2 NIL NIL NIL NIL
    1 NIL NIL NIL NIL 1 NIL NIL NIL NIL NIL NIL NIL 1 NIL NIL NIL NIL NIL NIL
    NIL 1 NIL 1 NIL 0 NIL 0)

SYNOPSIS

(defmethod get-it ((re recurring-event))

recurring-event/make-re [ Functions ]

[ Top ] [ recurring-event ] [ Functions ]

DESCRIPTION

 Make an instance of a recurring-event object, which allows for the
 periodic/cyclic return of given data. The recurring-event object is
 intended for situations in which the user would like to perform an action
 or collect data every several events, but with a varying cycle period.

ARGUMENTS

 - A list of two-item lists that indicate the period pattern by which the
   action or data collection is to be performed. For example, a value such
   as '((2 3) (3 2) (5 3) (8 2)) will result in the action being performed
   every 2 events three times, then every 3 events twice, every 5 events
   thrice etc.

OPTIONAL ARGUMENTS

 keyword arguments:
 - :return-data. If the recurring-event object is to be used to collect
   data, that data can be specified in this slot, with the indices into this
   data in the return-data-cycle slot. The return-data and return-data-cycle
   slots must be used together.
 - :return-data-cycle. If data is specified using :return-data, the indices
   into that data must be specified here. For example, the value 
   '((0 3) (3 2) (2 1) (1 5)) will the data item at (nth 0) thrice, that at
   (nth 3) twice, that at (nth 2) once, and that at (nth 1) five times.
 - :id. An optional ID can also be specified for the recurring-event object
   created. 

RETURN VALUE

 A recurring-event object.

EXAMPLE

;;; Simple usage with no specified data
(make-re '((2 3) (3 2) (5 3) (8 2)))
=> 
RECURRING-EVENT: current-period: 2, current-repeats: 3
                 pcount: -1, rcount: 0
                 return-data: NIL, return-data-cycle: NIL
CIRCULAR-SCLIST: current 1
SCLIST: sclist-length: 4, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: NIL, tag: NIL, 
data: ((2 3) (3 2) (5 3) (8 2))

;;; Usage with specified :return-data and :return-data-cycle
(make-re '((2 3) (3 2) (5 3) (8 2))
         :return-data '(a b c d)
         :return-data-cycle '((0 3) (3 2) (2 1) (1 5)))

=>
RECURRING-EVENT: current-period: 2, current-repeats: 3
                 pcount: -1, rcount: 0
                 return-data: (A B C D), return-data-cycle: 
CYCLE-REPEATS: folded: ((0 3) (3 2) (2 1) (1 5))
CIRCULAR-SCLIST: current 0
SCLIST: sclist-length: 11, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: NIL, tag: NIL, 
data: (0 0 0 3 3 2 1 1 1 1 1)
**************

CIRCULAR-SCLIST: current 1
SCLIST: sclist-length: 4, bounds-alert: T, copy: T
LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
NAMED-OBJECT: id: NIL, tag: NIL, 
data: ((2 3) (3 2) (5 3) (8 2))

SYNOPSIS

(defun make-re (data &key return-data return-data-cycle id)

recurring-event/on-it [ Methods ]

[ Top ] [ recurring-event ] [ Methods ]

DESCRIPTION

 Test to determine whether the method is currently at a period boundary. The
 object keeps track of its own internal state and position counter. This
 method is most effective when called repeatedly in a loop.

 Note that NIL is returned for the full first cycle rather than T then nil
 as it is assumed that the beginning is a special case where state would
 not want to be changed.

ARGUMENTS

 - A recurring-event object.

RETURN VALUE

 T or NIL.

EXAMPLE

;;; Straightforward usage
(let ((re (make-re '((2 3) (3 2) (5 3) (8 2)) 
                   :return-data '(a b c d)
                   :return-data-cycle '((0 3) (3 2) (2 1) (1 5)))))
  (loop repeat 50 collect (on-it re)))

=> (NIL NIL T NIL T NIL T NIL NIL T NIL NIL T NIL NIL NIL NIL T NIL NIL NIL NIL
    T NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL NIL T NIL NIL NIL NIL NIL NIL
    NIL T NIL T NIL T NIL T)

SYNOPSIS

(defmethod on-it ((re recurring-event))