<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
</head>
<body bgcolor="#ffffff" text="#000000">
<br>
<br>
Attila Lendvai wrote:
<blockquote
cite="mid:AANLkTi=T65pMpjU_uv-p0-vzRphHPfYW+HuAGhy62dHt@mail.gmail.com"
type="cite">
<blockquote type="cite">
<pre wrap="">macros that are useful and should be allowed. It is just that
anaphoric macros, despite all their cuteness, tax code readers
unnecessarily hard and thus have not been adopted as acceptable
practice in multi-programmer environments.
</pre>
</blockquote>
<pre wrap=""><!---->
well, it's one opinion.
there's at least one counter example in our team of 4. and i
personally do like reasonable usage of anaphoric macros, even when
done by my colleagues. and the reason is exactly that it *rises* code
readability for us.
our practice includes special coloring for "it" and avoids any usage
which is not blatantly trivial.
</pre>
</blockquote>
OK, if you're going to do that, that helps a lot.<br>
<br>
A problem with this is that code that starts<br>
blatently trivial can grow. This is one reason<br>
that you see enormous Perl scripts; people<br>
thought they'd be simple enough that Perl<br>
was appropriate, but they grow over time.<br>
<br>
Suddenly you have an outer "it" and an inner "it",<br>
and you need to "let" the outer one if you need<br>
to access that quantity in the inner one. And<br>
someone reading the code can get confuse<br>
about which one you mean.<br>
<br>
Instead of "awhen", what we use here is called<br>
when-bind. Example (real one, from actual<br>
airline code): <br>
<tt><br>
(or (when-bind (dmc (message-dmc (request-task-message rt)))<br>
(dmc-struct-maximum-number-of-fdrs-in-response dmc))<br>
(iatci-config :max-response-fdrs rt nil))<br>
</tt><br>
You specify the name. It's not anamorphic. The<br>
name can be meaningful, rather than "it". There<br>
are no conflicts. It does not get ugly when<br>
the code gets larger.<br>
<br>
The downside is that it's more verbose, because<br>
you have to put in the name of the variable, and<br>
there is one more level of paren to keep things<br>
Lispy.<br>
<br>
By the way, there is a sort of anamorphic thing<br>
in the "Clojure" dialect, where you can write<br>
little lambdas without arglists, by using<br>
$1 and $2 and so on to mean first arg,<br>
second arg, and so on. Again, he's trying<br>
to make programming with functions more<br>
friendly by making it more succinct, and I'm<br>
sure he'd also say "you should only use<br>
it for simple cases".<br>
<br>
If you are following good practices, you'd<br>
stop using these things when the code<br>
gets large. Having automatic refactoring<br>
IDE's that could do that would be one way<br>
of trying to get the best of both words.<br>
<br>
On the other hand, we do have an anmorphic<br>
macro that we sometimes use, in the sense<br>
that it makes up its own symbols. It is called<br>
define-class, and tries to be more like the<br>
Flavors class definer. The CLOS one, I think<br>
in an attempt to entirely avoid anamorphism,<br>
makes you spell out the names of the accessors<br>
(and/or readers and writers). define-class<br>
creates these names.<br>
<br>
<tt>(define-class puma-request-context (migration-request-context)<br>
((journey :type qapi-journey)<br>
(pnr :type qapi-pnr)<br>
(staged-pnr :type staged-puma-pnr)<br>
(pax-map :type list) ; a list containing elements of form
(staged-pax-name . qapi-pnr-passenger)<br>
(seg-map :type list) ; a list containing elements of form
(staged-segment . qapi-pnr-segment)<br>
(slices :type list) ; a list of qapi-pnr-slice<br>
(staging-to-action-map<br>
;; A list of two element sublists associating a staging object with
a QAPI action.<br>
:type list<br>
:initform nil)))</tt><br>
<br>
expands into<br>
<br>
<br>
<tt>(PROGN (DEFCLASS PUMA-REQUEST-CONTEXT (MIGRATION-REQUEST-CONTEXT)<br>
((JOURNEY :ACCESSOR<br>
PUMA-REQUEST-CONTEXT-JOURNEY<br>
:INITARG<br>
:JOURNEY<br>
:TYPE<br>
QAPI-JOURNEY)<br>
(PNR :ACCESSOR PUMA-REQUEST-CONTEXT-PNR :INITARG :PNR :TYPE
QAPI-PNR)<br>
(STAGED-PNR :ACCESSOR PUMA-REQUEST-CONTEXT-STAGED-PNR :INITARG<br>
:STAGED-PNR :TYPE STAGED-PUMA-PNR)<br>
(PAX-MAP :ACCESSOR PUMA-REQUEST-CONTEXT-PAX-MAP :INITARG
:PAX-MAP<br>
:TYPE LIST)<br>
(SEG-MAP :ACCESSOR PUMA-REQUEST-CONTEXT-SEG-MAP :INITARG
:SEG-MAP<br>
:TYPE LIST)<br>
(SLICES :ACCESSOR PUMA-REQUEST-CONTEXT-SLICES :INITARG
:SLICES :TYPE<br>
LIST)<br>
(STAGING-TO-ACTION-MAP :ACCESSOR<br>
PUMA-REQUEST-CONTEXT-STAGING-TO-ACTION-MAP :INITARG<br>
:STAGING-TO-ACTION-MAP :TYPE LIST :INITFORM NIL)))<br>
(DECLARE-LIST-OF PUMA-REQUEST-CONTEXT)<br>
(DEFUN MAKE-PUMA-REQUEST-CONTEXT (&REST<br>
QUUX::KEYS<br>
&KEY<br>
JOURNEY<br>
PNR<br>
STAGED-PNR<br>
PAX-MAP<br>
SEG-MAP<br>
SLICES<br>
STAGING-TO-ACTION-MAP<br>
&ALLOW-OTHER-KEYS)<br>
(DECLARE<br>
(IGNORABLE JOURNEY PNR STAGED-PNR PAX-MAP SEG-MAP SLICES<br>
STAGING-TO-ACTION-MAP))<br>
(DECLARE (DYNAMIC-EXTENT QUUX::KEYS))<br>
(APPLY #'MAKE-INSTANCE 'PUMA-REQUEST-CONTEXT QUUX::KEYS))<br>
(DEFINE-COMPILER-MACRO<br>
MAKE-PUMA-REQUEST-CONTEXT<br>
(&REST QUUX::ARGS)<br>
(LIST* 'MAKE-INSTANCE<br>
(LIST* (LIST* 'QUOTE (LIST 'PUMA-REQUEST-CONTEXT))<br>
QUUX::ARGS)))<br>
(FIND-CLASS 'PUMA-REQUEST-CONTEXT))</tt><br>
<br>
Some of our code uses this and some does not, at the whim<br>
of the programmer (perhaps that's poor practice). However,<br>
I haven't noticed this causing any problems.<br>
<br>
<br>
</body>
</html>