Let's begin SchemeOS

Chris Bitmead chrisb@Ans.Com.Au
Mon, 23 Mar 1998 13:03:14 +0000


Well I've done a little bit of thinking and I've written a few
ideas down. At least it's a place to start discussions. If you
agree with me that a SchemeOS is all about object modelling and
persistent stores, then I invite comments. If you don't like
persistent stores, hit delete now.

My main concern is that I am still thinking in too much of a UNIX
way, No doubt some more lateral thinkers may be able to put
forward more elegant things. But we need to start somewhere.

The following are object definitions in  what is, as far as I
can  make out, RScheme's class definition style. As a quick
overview, the syntax is

(define-class <name> (<super-class>)
  slot...
  )

where a slot is either just
<name>
or
(name :type <classname>)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; The root object of the whole persistent store
(define-class <root> (<directory>)
  (users :type <users>)      ; The users on the system
  (devices :type <devices>))  ; devices on the system

; <users> A collection of all the users on the system
(define-class <users> (<collection>)
  )

; <user> class definition
; This class gives the basic information about a user
(define-class <user> (<object>)
  id      ; login id
  name    ; name
  (threads <collection>)
  (mail-box :type <mail-box>) ; The user's incoming mail box
  (root :type <directory>)) ; A storage area for the user's
persistent objects.

; <mail-box> class definition
; This holds a collection of mail items
(define-class <mail-box> (<collection>)
  )

; <directory> class definition
; Yeah sure, the traditional UNIX idea of a directory which
; is a map between strings and objects is still a useful idea.
; Just not as useful as it was previously.
(define-class <directory> (<map>))

(define-method insert ((directory <directory>) (key string)
object)
  (insert directory (make map-item :key string :object object)))

; <letter> class definition
; A letter is an piece of email
; It is basicly a text document with some header information.
(define-class <letter> (<text>)
  (headers :type <map>) ; A map between header keys and values.
  (attachments :type <collection>))

; <text> class definition
; This class holds a traditional ascii text file
; Each line is an item in the collection.
(define-class <text> (<collection>))

; <collection> class definition
; General purpose collection class, that can hold groups of
objects.
(define-class <collection> (<object>)
  a-list)
  
; <map> class definition
; general purpose collection that indexes keys to objects
(define-class <map> (<collection>))

(define-class <map-item> (<object>)
  key
  object)

; <thread> class definition
; stores general information about a thread running in the system

(define-class <thread> (<object>)
  (user :type <user>) ; owner of thread
  priority)
  
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;EXAMPLES;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; Kill all the threads started by chrisb

(for-each kill (threads (get-user-by-id (user *root*) "chrisb")))

; let's view every object in a directory. In true OO style, it
doesn't matter 
; if some things in the directory are text, some are emails, some
are folders, some ; are html documents. A different viewer will
be started to view different types of ; files.

(for-each view (collection->list some-directory))

; send some email

(send (make-letter :to "lispos@lispos.org" :subject "Do Code"
				   (make-text-from-stdin)))
Please write some
code please everybody
^D

; let's do a mail merge and store a copy ourselves in a private
mail
; folder for the corresponding person too.

(set! *friends* '("bill@foo.com", "jim@bar.com", "jane@baz.org"))
(set! *form-letter* (make-text-from-stdin))
Hi! I've changed my email address!
^D

(for-each (lambda (person)
		   (let ((letter) (make-letter 
						   :to person 
						   :subject "change of address"
						   *form-letter*))
			 (insert-mail-items (item *mail-folders* person) letter)
			 (send letter)))
		 *friends*)
			 
;Now we might implement a crude implementation of UNIX style grep
like this...

(define-method grep ((pattern string) (text <text>))
  (list->text
   (filter (lambda (line) (regexp-match? pattern line)) 
		   (text->list text))))

(define *file1* (make-text 
				 "line1a"
				 "line2b"
				 "line3a"))

(print-text (grep "a" *file1*))
line1a
line3a	

(print-text (grep "1" *file1*))
line1a

; Now to move all the lispos mailing list messages from your main
mail
; box into a lispos mail box...

(insert-mail-items 
 *lispos-mail-box* 
 (remove-items *mail-box*
			   (lambda (letter)
				 (regexp-match? (get-item (headers letter) 
					                   "From")
                                                "lispos"))))
(commit)

; Backup the files of all the users whose name is between A-K.

(backup (tape-drive (devices *root*))
		(filter (lambda (user) (regexp-match? "^a-k" (name user)))
				(root (users *root*))))

; Change the system time
(set-date "20 Mar 1998" (clock (devices *root*)))



-- 
Chris Bitmead
http://www.ans.com.au/~chrisb
mailto:chrisb@ans.com.au