[munich-lisp] context handling via CLOS and (eql form)
Christian Schuhegger
Christian.Schuhegger at gmx.de
Sat Sep 10 06:40:58 UTC 2005
hi,
here is a quick dummy example of what i intended to explain yesterday
about handling context by explicitely threading a context parameter
through your application:
-- start --
(defun test ()
(let ((context '((condition-1 . yes)(condition-2 . no)(condition-3 .
perhaps))))
(function-example-1 context 1 2)))
(defun function-example-1 (context other-arg-1 other-arg-2)
(let ((condition-1 (cdr (assoc 'condition-1 context)))
(condition-2 (cdr (assoc 'condition-2 context))))
(function-example-1-with-context condition-1 condition-2
other-arg-1 other-arg-2)))
(defmethod function-example-1-with-context (condition-1 condition-2
other-arg-1 other-arg-2)
(declare (ignorable condition-1 conditon-2 other-arg-1 other-arg-2))
(error "not implemented context"))
(defmethod function-example-1-with-context ((condition-1 (eql 'yes))
(condition-2 (eql 'no)) other-arg-1 other-arg-2)
(declare (ignorable condition-1 conditon-2))
(format t "c1: yes c2: no arg1: ~A arg2: ~A~%" other-arg-1 other-arg-2))
(defmethod function-example-1-with-context ((condition-1 (eql 'yes))
(condition-2 (eql 'yes)) other-arg-1 other-arg-2)
(declare (ignorable condition-1 conditon-2))
(format t "c1: yes c2: yes arg1: ~A arg2: ~A~%" other-arg-1 other-arg-2))
-- end --
[21]> (test)
c1: yes c2: no arg1: 1 arg2: 2
as mentioned yesterday in the presentation often when you look at code
that handles context you see a big if-then-else tree. this is very
confusing and cannot be easily extended. in the above example you see no
single if-then-else and it is additive in the sense that when you would
like to add another combination of your predicates (conditions) you just
add another defmethod.
besides that, normally a program with context uses conditions/predicates
to determine its actions. therefore i do not really see why the
introduction of the concept 'layer' could help? i may be wrong, but in
my current understanding a layer is just a name for a certain predicate
combination, e.g.
layer-1 := condition-1 == yes && condition-2 == no
as you also see above with condition-3 (which is actually not used :) )
a predicate does not have to be binary, e.g. it is not restricted to the
only values true and false. you can have even enumerated predicates like
for example certain categories of screen size
'small := width 40 characters
'medium := width 80 characters
'big := width 120 characters
'large := more than 140 characters
....
i decided to use an explicite parameter to the method called context and
not a 'special' variable with dynamic scope. this has the disadvantage
that you have to write the parameter in a lot of places (this is a one
time disadvantage when you write the code), but it has the advantage
that every function/method can be easily tested, because you explicitely
hand in the context.
i originally used the above technique in an embedded language (lisp plc
programming environment : LPPE) where i had to output different 'machine
code' instructions depending on the target hardware (not really but you
can imagine it as: i386, ARM, alpha, ...) and depending on the element
in the abstract syntax tree. therefore the methods take two (eql form)
parameters, one is the target hardware type and one is the type of the
AST-node.
--
Christian Schuhegger
http://www.el-chef.de/
More information about the munich-lisp
mailing list