In yesterday's write-up I started touching scheme. It is part of my attempt to study the language. It might be a bit ambitious as a first "real" problem, though. So until I reach a solution for that, I will try and solve a few randomly selected different problems. Most of them will be something I already know how to say in other languages, the aim for most of them should be a cleaner solution. In the end I must prove to myself that it is worth learning scheme.
Today's problem
Things or the theory of anything
There were a lot of discussions going in the Drupal development circles around what is a node, what is a user, is a user a node, is a taxonomy term a node, etc... In Amsterdam a few of us were really impressed my anymeta by mediamatic, where everything is a thing.
So, let's try to model that. Mind you no web server stuff is coming out of this antytime soon.
Express a type system, where everything is a thing. Different things must be uniquely identifiable, maintain their creation and last modification times, and have some variably structured content. Example things: a person, a story, a story with revisions.
What is a thing?
A first approximation
(define-struct thing (id created modified content))should be the most general thing definition. Scheme is dynamically typed, so this definition should allow for differently structured content.
;defines a thing structure (integer,date, date, mixed )
(define-struct thing (id created modified content))
;defines a person structure of (string, string, string)
(define-struct person (name title surname))
;defines a story structure of (string, string, string, person)
(define-struct story (title body abstract author))
(define a-thing (make-thing 1 '1.2.2006 '1.2.2006
(make-story
"a title"
"In yesterday's write-up I started touching scheme. It
is part of my attempt to study the language. It might
be a bit ambitious as a first "real" problem, though."
"In yesterday's write-up"
(make-person "vlado" '() "dikini"))))
;example query
(person-name (story-author (thing-content my-first-thing)))
="Vlado"
So far so good. There is a problem though a person is a thing as well. So the above should change to:
(define vlado (make-thing 2 '21.07.1970 '1.2.2006
(make-person "Vlado" "Mr" "dikini")))
(define a-thing (make-thing 1 '1.2.2006 '1.2.2006
(make-story
"a title"
"In yesterday's write-up I started touching scheme. It
is part of my attempt to study the language. It might
be a bit ambitious as a first "real" problem, though."
"In yesterday's write-up"
vlado)))
Now I have two kinds of things, but there is something, which really bothers me - this definition, in my opinion is not flexible enough. Since content can be a composition of things - like a couple of authors + editor + a set of photographs + text. This really tends to move me towards flexible definitions of thing structure and postponing resolving a thing's structure until thing definition time.
Take 2
Some time later, the same idea, but using only lists and pairs.
;make-thing:
number date date string|article|person -> list of pairs
(define (make-thing id created modified content)
(list (cons 'id id)
(cons 'created created)
(cons 'modified modified)
(cons 'content modified)))
;make-thing: string string string -> list of pairs
(define (make-article title teaser body)
(list (cons 'type 'article)
(cons 'title title)
(cons 'teaser teaser)
(cons 'body body)))
;make-thing: number string string string -> list of pairs
(define (make-person title name surname)
(list (cons 'type 'person)
(cons 'title name)
(cons 'name name)
(cons 'surname surname)))This version is definitely longer. But it reveals, some patterns - for example the different content types have similar looking structure. This means that I should be able to use the same functions to traverse any content type. There is a pleasing similarity to xml - these are tree structures. There is a simmetry with SQL as well, so it should be possible to minimise the code there due to uniform traversal of the tree. This excercise starts looking like language design. After pasting this here I asked myself, yes but you should be able to put a thing or a list of things.
The obligatory print the data game
As a finishing touch for this phase some classic printing:
(define (print-tuple tuple)
(begin
(display (string-append
(symbol->string(car tuple))
": "
(cond
[(number? (cdr tuple))
(number->string (cdr tuple))]
[(symbol? (cdr tuple))
(symbol->string (cdr tuple))]
[(string? (cdr tuple))
(cdr tuple)]
)))
(newline)))
(define (print-thing tuples)
(cond
[ (empty? tuples) (newline)]
[ (list? tuples) (begin
(print-tuple (car tuples))
(print-thing (cdr tuples)))]))
(define (print-things things)
(cond
[(empty? things) (newline)]
[else
(begin
(print-thing (car things))
(print-things (cdr things)))]))
(print-things
(list
(make-thing 1 "21.7.1970" "1.2.2005" "a content")
(make-thing 2 "22.7.1970" "1.2.2005" "another string")))And finally the output of the above:
Welcome to DrScheme, version 301. Language: Pretty Big (includes MrEd and Advanced Student). id: 1 created: 21.7.1970 modified: 1.2.2005 content: 1.2.2005 id: 2 created: 22.7.1970 modified: 1.2.2005 content: 1.2.2005
note:all this code is for mzscheme, that is "Pretty Big Scheme language" in DrScheme.