[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