;;; The code below shows: (1) How to store infomation about people and ;;; their jobs as two types of Lisp data structures: structures and ;;; objects. The generated data structures two types of objects are ;;; stored in global variables. (2) How to (3) How to read ;;; information from a input data file to do the same thing. ;;; --------------------------- ;;; defstruct ;;; --------------------------- ;;; A list of all employees, a global (defvar *all-people* nil) ;;; Define 2 structures: people and job (defstruct person (name nil) (age 0) (job nil)) (defstruct job (title 'peon) (hours-per-week 40) (salary 8.5)) ;;; Creates a person Jane, and adds structure to global variable (push (make-person :name 'Jane :age 40 :job (make-job :title 'doctor :salary 50)) *all-people*) ;;; Creates a person Fred, and adds structure to global variable (push (make-person :name 'Fred :age 32 :job (make-job :title 'Burger-flipper :hours-per-week 20)) *all-people*) ;;; Assigns a salary to an person (defun give-salary (p amount) (setf (job-salary (person-job p)) amount)) ;;; Finds Fred, and assigns a salary to him. Note the use of the ;;; function find with a keyword, which is very convenient to find a ;;; person (give-salary (find 'fred *all-people* :key #'(lambda (x) (person-name x))) 9) ;;; The above can be re-written in an equivalent way as follows: (give-salary (find 'fred *all-people* :key #'person-name) 9) ;;; --------------------------- ;;; declass ;;; --------------------------- ;;; In Spanish, a person is "persona" and job is "trabajo". We will ;;; use the Spanish words to avoid clash with the above defined ;;; structures. Otherwise, the code does the same as above. (defvar *todo-persona* nil) (defclass persona () ((name :accessor name :initform nil :initarg :name) (age :accessor age :initform nil :initarg :age) (job :accessor job :initform nil :initarg :job))) (defclass trabajo () ((title :accessor title :initform 'peon :initarg :title) (hours-per-week :accessor hours :initform 40 :initarg :hours-per-week) (salary :accessor salary :initform 8.5 :initarg :salary))) (push (make-instance 'persona :name 'Jane :age 40 :job (make-instance 'trabajo :title 'doctor :salary 50)) *todo-persona*) (push (make-instance 'persona :name 'Fred :age 32 :job (make-instance 'trabajo :title 'burger-flipper :hours-per-week 20)) *todo-persona*) ;;; Assigns a salary to an employee (defmethod set-salary ((someone persona) amount) (setf (salary (job someone)) amount)) ;; Assigs Fred a salary of $9/hour (set-salary (find 'fred *todo-persona* :key #'name) 9) ;;; --------------------------- ;;; Reading data from a file ;;; --------------------------- (defun load-people (filename) (with-open-file (in-stream filename :direction :input) (let ((n (read in-stream nil))) (dotimes (count n nil) (let* ((person (read in-stream nil)) (job (third person))) ;; adds person to struct list (push (make-person :name (first person) :age (second person) :job (make-job :title (first job) :hours-per-week (second job) :salary (third job))) *all-people*) ;; adds person to class list (push (make-instance 'persona :name (first person) :age (second person) :job (make-instance 'trabajo :title (first job) :hours-per-week (second job) :salary (third job))) *todo-persona*)))))) ;;; Try loading this file and looking at the values of the global ;;; variables. Then run (load-people "people-data.lisp") and check ;;; the values of the global variables.