From: Benigno Uria
Subject: Separation of concerns in Lisp. How would you implement it?
Date: 
Message-ID: <4612f93a$1_1@filemon2.isp.telecable.es>
Hello,

I'm coding a genetic programming library in Lisp. I have a doubt trying 
to separate the genetic algorithm code from the code that outputs the 
results.

I want to be able to use different loggers: log to screen, log to a 
database, log to files... Ideally I would be able to use many of these 
at the same time; but that's not really critical, just desirable.

I need different functions (or methods, that's part of my question) to 
log experiment arguments, runs (an experiment will almost always consist 
of several runs), and population measurements (mean fitness, max 
fitness...).

As I see it I have several options:

1) Hardcode the logging code into the genetic programming code. This 
would be a PITA to change afterward. So I discard this one.

2) Pass the logging functions as arguments to the GP code. I don't like 
this solution neither. The GP code already requires a long list of 
parameters. And the calls to the logging functions would obscure the GP 
code.

3) Use functions that redefine the GP functions so they call the logging 
functions before and after the GP code is executed. This looks to me 
like a nasty hack and feels like I would be reinventing the wheel 
(:before and :after methods). And it would make rather difficult to 
change the logging method once it is established (I could save the 
original function in the property list, but that seems even nastier).

4) Use :before and :after methods. This option looks elegant. BUT I 
don't know how I could use several logging methods at the same time. 
I've made some experiments using the REPL and it seems I can only have 
only one :before and only one :after method for a given method.

CL-USER> (defmethod foo ((a symbol) (b fixnum))
	   (format t "~A~A" a b))
STYLE-WARNING: implicitly creating new generic function FOO
#<STANDARD-METHOD FOO (SYMBOL FIXNUM) {AF07239}>
CL-USER> (defmethod foo :before ((a symbol) (b fixnum))
	   (format t "->"))
#<STANDARD-METHOD FOO :BEFORE (SYMBOL FIXNUM) {AF8D709}>
CL-USER> (foo 'test 5)
->TEST5
NIL
CL-USER> (defmethod foo :before ((a symbol) (b fixnum))
	   (format t "**"))
STYLE-WARNING: redefining FOO :BEFORE (SYMBOL FIXNUM) in DEFMETHOD
#<STANDARD-METHOD FOO :BEFORE (SYMBOL FIXNUM) {AFF4D61}>
CL-USER> (foo 'test 5)
**TEST5
NIL

Although this would facilitate changing the logging method once it's 
been established, so I'm not sure if I want this or not.

And at present moment GP code is made up of functions, not methods. Some 
of the functions use default parameter values. I would not be able to 
easily transform them into methods (necessary to use :before and :after).

How would you implement it? Am I missing any obvious and elegant way?

Thank you for your help.

Benigno Ur�a.

From: Kaz Kylheku
Subject: Re: Separation of concerns in Lisp. How would you implement it?
Date: 
Message-ID: <1175649700.637268.243000@w1g2000hsg.googlegroups.com>
On Apr 3, 6:02 pm, Benigno Uria <·············@gmail...> wrote:
> 2) Pass the logging functions as arguments to the GP code. I don't like
> this solution neither. The GP code already requires a long list of
> parameters. And the calls to the logging functions would obscure the GP
> code.

Or Pascal Costanza's dynamically scoped functions---so that they don't
occupy argument space.

AspectL, ContextL.

> I've made some experiments using the REPL and it seems I can only have
> only one :before and only one :after method for a given method.

For the same specialization yes. To get more, you have to vary the
specialization of the parameters, which can be inconvenient.
From: Pascal Bourguignon
Subject: Re: Separation of concerns in Lisp. How would you implement it?
Date: 
Message-ID: <87mz1or1ok.fsf@voyager.informatimago.com>
"Kaz Kylheku" <········@gmail.com> writes:

> On Apr 3, 6:02 pm, Benigno Uria <·············@gmail...> wrote:
>> 2) Pass the logging functions as arguments to the GP code. I don't like
>> this solution neither. The GP code already requires a long list of
>> parameters. And the calls to the logging functions would obscure the GP
>> code.
>
> Or Pascal Costanza's dynamically scoped functions---so that they don't
> occupy argument space.
>
> AspectL, ContextL.
>
>> I've made some experiments using the REPL and it seems I can only have
>> only one :before and only one :after method for a given method.
>
> For the same specialization yes. To get more, you have to vary the
> specialization of the parameters, which can be inconvenient.

But you don't need more than one :before or :after method.  If you
want to log to several logs, you can use a broadcast-stream, or
implement a similar mechanism with your log system.

(defvar *log* (make-broadcast-stream))  ; /dev/null by default.
(defun log (ctrlstr &rest args) (apply (function format) *log* ctrlstr args))
(defmethod do-something :before (self) (log "~&Will do something~%"))
(defmethod do-something :after  (self) (log "~&Did something~%"))

;; And now you can write:

(defclass x () ())
(defmethod do-something ((self x)) (format t "~&I'm doing something~%"))


[94]> (with-open-file (log "/tmp/log" :direction :output :if-does-not-exist :create :if-exists :append)
       (let ((*log* (make-broadcast-stream log *standard-output*)))
        (do-something (make-instance 'x))))
Will do something
I'm doing something
Did something
NIL
[95]> (shell "cat /tmp/log") ; I ran the above sexp several times already ;-)
Will do something
Did something
Will do something
Did something
Will do something
Did something
0
[96]> 

-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Benigno Uria
Subject: Re: Separation of concerns in Lisp. How would you implement it?
Date: 
Message-ID: <4613ea05_4@filemon2.isp.telecable.es>
Kaz Kylheku wrote:
> On Apr 3, 6:02 pm, Benigno Uria <·············@gmail...> wrote:
>> 2) Pass the logging functions as arguments to the GP code. I don't like
>> this solution neither. The GP code already requires a long list of
>> parameters. And the calls to the logging functions would obscure the GP
>> code.
> 
> Or Pascal Costanza's dynamically scoped functions---so that they don't
> occupy argument space.
> 
> AspectL, ContextL.
> 
>> I've made some experiments using the REPL and it seems I can only have
>> only one :before and only one :after method for a given method.
> 
> For the same specialization yes. To get more, you have to vary the
> specialization of the parameters, which can be inconvenient.
> 

I've skimmed AspectL homepage and although it looks useful I won't use 
it this time. I don't want to force the GP lib users to understand AOP 
and AspectL too. I want to keep the library as simple as possible.

Thank you.

Benigno Ur�a
From: Tim Bradshaw
Subject: Re: Separation of concerns in Lisp. How would you implement it?
Date: 
Message-ID: <1175685162.466948.151190@w1g2000hsg.googlegroups.com>
On Apr 4, 2:02 am, Benigno Uria <·············@gmail...> wrote:

> I want to be able to use different loggers: log to screen, log to a
> database, log to files... Ideally I would be able to use many of these
> at the same time; but that's not really critical, just desirable.

>
>
> How would you implement it? Am I missing any obvious and elegant way?

Make all your logging use standard interfaces (functions).  Have a
special variable called *LOGGER* say, and implement the user functions
as:

(defun log (...)
  (log/logger *logger* ...))

LOG/LOGGER is, of course, a GF which can now specialize on its first
argument as well as any others.  You want default methods for *logger*
being NULL, and probably a method like this:

(defmethod log/logger ((logger list) ...)
  (loop for l in logger
        do (log/logger l ...)))

Finally have a WITH-LOGGER macro.