Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Trouble with labels

26 views
Skip to first unread message

Barry Margolin

unread,
Apr 10, 2001, 1:14:49 PM4/10/01
to
In article <4sf6dto7mf556cvah...@4ax.com>,
<isc...@hotmail.com> wrote:
>
>How can I make a function defined in labels refer to another function defined
>in the same labels body?
>
>For example (this is from SICP page 223):
>(defun make-account (balance)
> (labels ((withdraw (amount)
> (if (>= balance amount)
> (progn
> (setf balance (- balance amount))
> balance)
> (format t "Insufficient funds")))
> (deposit (amount)
> (setf balance (+ balance amount))
> balance)
> (dispatch (m)
> (cond
> ((equal m 'withdraw) withdraw)
> ((equal m 'deposit) deposit)
> (t (format t "Unknown request -- MAKE-ACCOUNT")))))
> dispatch))
>
>This gets an error:
>; MAKE-WITHDRAW
>;;;*** Warning in (SUBFUNCTION (LABELS DISPATCH) MAKE-ACCOUNT): WITHDRAW
>assumed special
>;;;*** Warning in (SUBFUNCTION (LABELS DISPATCH) MAKE-ACCOUNT): DEPOSIT
>assumed special
>;;;*** Warning in MAKE-ACCOUNT: DISPATCH assumed special
>; MAKE-ACCOUNT

The reason you're getting these errors is because you're referring to the
function names as if they were variables. To refer to a function, you have
to use #'<function-name>, i.e.:

(dispatch (m)
(cond
((equal m 'withdraw) #'withdraw)
((equal m 'deposit) #'deposit)
(t (format t "Unknown request -- MAKE-ACCOUNT")))))

BTW, wouldn't it be better if the last clause used ERROR rather than
FORMAT? In fact, you could write it as:

(dispatch (m)
(ecase m
(withdraw #'withdraw)
(deposit #'deposit))))

ECASE will take care of the matching and error handling for you.

--
Barry Margolin, bar...@genuity.net
Genuity, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Tim Moore

unread,
Apr 10, 2001, 1:24:02 PM4/10/01
to
On Tue, 10 Apr 2001 isc...@hotmail.com wrote:

>
> How can I make a function defined in labels refer to another function defined
> in the same labels body?

Remember, this isn't Scheme, but Common Lisp:

(defun make-account (balance)
(labels ((withdraw (amount)
(if (>= balance amount)
(progn
(setf balance (- balance amount))
balance)
(format t "Insufficient funds")))
(deposit (amount)
(setf balance (+ balance amount))
balance)
(dispatch (m)
(cond

((equal m 'withdraw) #'withdraw)
((equal m 'deposit) #'deposit)
(t (format t "Unknown request -- MAKE-ACCOUNT")))))

#'dispatch))

Also, the syntax for invoking the dispatch function isn't as compact as it
is in Scheme e.g.:
(funcall (funcall acct 'withdraw) 69.00)

Tim

Geoff Summerhayes

unread,
Apr 10, 2001, 1:28:52 PM4/10/01
to

<isc...@hotmail.com> wrote in message news:4sf6dto7mf556cvah...@4ax.com...

>
> How can I make a function defined in labels refer to another function defined
> in the same labels body?
>
> (cond
> ((equal m 'withdraw) withdraw)

should be: ((equal m 'withdraw) (withdraw))


> ((equal m 'deposit) deposit)

should be: ((equal m 'deposit) (deposit))

> (t (format t "Unknown request -- MAKE-ACCOUNT")))))
> dispatch))

should be: (dispatch)))

> This gets an error:
> ; MAKE-WITHDRAW
> ;;;*** Warning in (SUBFUNCTION (LABELS DISPATCH) MAKE-ACCOUNT): WITHDRAW
> assumed special
> ;;;*** Warning in (SUBFUNCTION (LABELS DISPATCH) MAKE-ACCOUNT): DEPOSIT
> assumed special
> ;;;*** Warning in MAKE-ACCOUNT: DISPATCH assumed special
> ; MAKE-ACCOUNT
>

Without the parenthesies Lisp will look for variables with those names
not functions.

Geoff

Geoff Summerhayes

unread,
Apr 10, 2001, 1:40:15 PM4/10/01
to

"Geoff Summerhayes" <sNuOmS...@hNoOtSmPaAiMl.com> wrote in message news:td6ggj2...@corp.supernews.com...

>
>
> should be: ((equal m 'withdraw) (withdraw))
>
> should be: ((equal m 'deposit) (deposit))
>
> should be: (dispatch)))

Opened my mouth too soon, just took a closer look at the code.

Should be #'withdraw #'deposit #'dispatch instead of (withdraw),
(deposit), and (dispatch)

Oops, Geoff


Erik Naggum

unread,
Apr 11, 2001, 8:58:10 AM4/11/01
to
* isc...@hotmail.com

> How can I make a function defined in labels refer to another function
> defined in the same labels body?

The same way you refer to functions everywhere else in Common Lisp.

I honestly do not understand why you are not using a Scheme system to
learn Scheme when you don't know Common Lisp well enough to know how to
refer to functions. Perhaps you think that Scheme is a Lisp and Common
Lisp is a Lisp, so it should work? Just because two human languages have
Indo-European roots doesn't mean that they can be interchanged if you
want to learn one of them, either.

> For example (this is from SICP page 223):
> (defun make-account (balance)
> (labels ((withdraw (amount)
> (if (>= balance amount)
> (progn
> (setf balance (- balance amount))
> balance)
> (format t "Insufficient funds")))
> (deposit (amount)
> (setf balance (+ balance amount))
> balance)
> (dispatch (m)

> (cond
> ((equal m 'withdraw) withdraw)

> ((equal m 'deposit) deposit)


> (t (format t "Unknown request -- MAKE-ACCOUNT")))))
> dispatch))

This is what object-oriented programming looks like in Scheme, with
message-passing as the dispatch paradigm, using closures to hold the
data. If you want to understand what it does, stick to Scheme and learn
how it works in Scheme. Then see if the same concept, once understood,
is applicable anywhere else and whether it may be grafted into any other
system. (IMNSHO, it neither can nor should be.)

Scheme and Common Lisp are extremely different languages. You should not
assume that you can make Scheme code become Common Lisp code with a few
minor changes. For instance, set! in Scheme is defined not to have a
useful value. setf in Common Lisp is defined to have the value of the
last value. This means that any Common Lisp programmer will look at your
code and wonder why you're doing what you're doing, if there's something
special going on. And why use equal with symbols? I briefly wondered
whether that meant that m could be a string. What use is writing out
error messages that don't even say what's wrong? This (among a host of
other things) tells me that the whole example is designed to be used only
as a simple toy to illustrate something, just as Scheme is.

Here's how I would have written a similarly skeletal example in (real)
Common Lisp:

(defclass account ()
((balance :initarg :deposit :initform 0 :accessor balance)))

(defmethod withdraw ((account account) amount)
(decf (balance account) amount))

(defmethod deposit ((account account) amount)
(incf (balance account) amount))

(defmethod withdraw :before ((account account) amount)
(unless (<= amount (balance account))
(error "~A has insufficient funds to withdraw ~A." account amount)))

#:Erik
--
I found no peace in solitude.
I found no chaos in catastrophe.
-- :wumpscut:

cbbr...@hex.net

unread,
Apr 11, 2001, 3:36:03 PM4/11/01
to
Erik Naggum <er...@naggum.net> writes:
> (defmethod withdraw :before ((account account) amount)
> (unless (<= amount (balance account))
> (error "~A has insufficient funds to withdraw ~A." account amount)))

.. and THAT is the sort of example that _should_ get used in
textbooks.

OO examples typically take on frivolous applications like "let's
classify animals!" or "let's classify colours!" which go exactly
_nowhere_ towards showing the gentle programmer how the construct
might actually be _useful_.

Graham demonstrates :before and :after methods using a similarly
frivolous "application" where people are saying things, and if it
involves the King, everything gets surrounded by "BOW" and "If the
king pleases," gestures. (Mind you, this puts a rather different
meaning to the phrase "affecting a lisp"...)
--
(reverse (concatenate 'string "gro.gultn@" "enworbbc"))
http://www.ntlug.org/~cbbrowne/resume.html
"Necessity is the mother of invention" is a silly proverb. "Necessity
is the mother of futile dodges" is much closer to the truth. The
basis of growth of modern invention is science, and science is almost
wholly the outgrowth of pleasurable intellectual curiosity.
-- Alfred N. Whitehead

Paolo Amoroso

unread,
Apr 11, 2001, 4:06:04 PM4/11/01
to
On 11 Apr 2001 12:58:10 +0000, Erik Naggum <er...@naggum.net> wrote:

> (defclass account ()
> ((balance :initarg :deposit :initform 0 :accessor balance)))
>
> (defmethod withdraw ((account account) amount)
> (decf (balance account) amount))
>
> (defmethod deposit ((account account) amount)
> (incf (balance account) amount))
>
> (defmethod withdraw :before ((account account) amount)
> (unless (<= amount (balance account))
> (error "~A has insufficient funds to withdraw ~A." account amount)))

I have a design question: why do you keep the code for checking for the
appropriate balance in a separate :AROUND method instead of adding it to
WITHDRAW's primary method? I can think of a few reasons:

- because performing a withdrawal and checking for an appropriate balance
are orthogonal operations
- for improving modularization, i.e. for making it easier to later add
other validation methods
- to emphasize a WITHDRAW protocol


Paolo
--
EncyCMUCLopedia * Extensive collection of CMU Common Lisp documentation
http://cvs2.cons.org:8000/cmucl/doc/EncyCMUCLopedia/

Kent M Pitman

unread,
Apr 11, 2001, 4:39:31 PM4/11/01
to
Paolo Amoroso <amo...@mclink.it> writes:

>
> On 11 Apr 2001 12:58:10 +0000, Erik Naggum <er...@naggum.net> wrote:
>
> > (defclass account ()
> > ((balance :initarg :deposit :initform 0 :accessor balance)))
> >
> > (defmethod withdraw ((account account) amount)
> > (decf (balance account) amount))
> >
> > (defmethod deposit ((account account) amount)
> > (incf (balance account) amount))
> >
> > (defmethod withdraw :before ((account account) amount)
> > (unless (<= amount (balance account))
> > (error "~A has insufficient funds to withdraw ~A." account amount)))
>
> I have a design question: why do you keep the code for checking for the
> appropriate balance in a separate :AROUND method instead of adding it to
> WITHDRAW's primary method? I can think of a few reasons:
>
> - because performing a withdrawal and checking for an appropriate balance
> are orthogonal operations
> - for improving modularization, i.e. for making it easier to later add
> other validation methods
> - to emphasize a WITHDRAW protocol

Because if you do override the primary method, you often don't want to lose
this error checking. And it's MUCH harder to override before, after, and
around methods than it is to override primary methods. I tend to put
overridable stuff in the primaries and non-overridable stuff in the
before/after methods and acts of desperation in the around methods.

Barry Margolin

unread,
Apr 11, 2001, 4:54:24 PM4/11/01
to
In article <Dm2B6.143647$lj4.4...@news6.giganews.com>,

<cbbr...@hex.net> wrote:
>Erik Naggum <er...@naggum.net> writes:
>> (defmethod withdraw :before ((account account) amount)
>> (unless (<= amount (balance account))
>> (error "~A has insufficient funds to withdraw ~A." account amount)))
>
>.. and THAT is the sort of example that _should_ get used in
>textbooks.
>
>OO examples typically take on frivolous applications like "let's
>classify animals!" or "let's classify colours!" which go exactly
>_nowhere_ towards showing the gentle programmer how the construct
>might actually be _useful_.

Actually, the above example is pretty silly. :before and :after methods
are mostly useful in subclasses or mixin classes, to add behavior without
totally overriding the primary method that you inherit. Putting the
:before method in the same class as the primary method doesn't really make
a whole lot of sense -- the error check could just as easily be put in the
primary method.

A better example of a :before method related to this would be something
like:

(defclass overclass-protection-mixin
()
(service-fee :accessor service-fee :type (real 0.0))
(companion-account :accessor companion-account :type account))

(defmethod withdraw :before ((overdraft-protection-mixin account) amount)
(let ((comp (companion-account account)))
(withdraw comp (+ amount (service-fee comp))))
(deposit amount account))

(defclass account-with-overdraft-protection
(account overdraft-protection-mixin))

Vladimir V. Zolotych

unread,
Apr 12, 2001, 3:32:53 AM4/12/01
to
Erik Naggum wrote:
>
> Here's how I would have written a similarly skeletal example in (real)
> Common Lisp:

Thanks for interesting "CL-only" example on subject rarely
(if ever) found in textbooks.

--
Vladimir Zolotych gsm...@eurocom.od.ua

Vladimir V. Zolotych

unread,
Apr 12, 2001, 3:55:05 AM4/12/01
to
Barry Margolin wrote:
>
> Actually, the above example is pretty silly.

Don't think so. I also read the original poster's message but
didn't guess to write something similar. So thanks to Erik and
to you for



> A better example of a :before method related to this would be something
> like:

[snip]

examples on very interesting and useful subject
that wouldn't be found somewhere else.

--
Vladimir Zolotych gsm...@eurocom.od.ua

Paolo Amoroso

unread,
Apr 12, 2001, 7:38:56 AM4/12/01
to
On Wed, 11 Apr 2001 22:06:04 +0200, Paolo Amoroso <amo...@mclink.it>
wrote:

> I have a design question: why do you keep the code for checking for the
> appropriate balance in a separate :AROUND method instead of adding it to
> WITHDRAW's primary method? I can think of a few reasons:

Oooops... Of course I meant :BEFORE. Sorry.

Erik Naggum

unread,
Apr 12, 2001, 9:36:45 AM4/12/01
to
* Barry Margolin <bar...@genuity.net>

> Actually, the above example is pretty silly. :before and :after methods
> are mostly useful in subclasses or mixin classes, to add behavior without
> totally overriding the primary method that you inherit. Putting the
> :before method in the same class as the primary method doesn't really
> make a whole lot of sense -- the error check could just as easily be put
> in the primary method.

Sigh. In real life, how you deal with withdrawal requests in the absence
of sufficient funds depends on the account. Add a credit limit, and you
need more work, for instance. The reaction to such a request is _not_
integral to the withdrawal process, and conflating the two processes of
updating the balance and dealing with insufficient funds is really silly,
because you need to reimplement the core operation (updating the balance)
in a subclass with different characteristics. That's bad design.

Erik Naggum

unread,
Apr 12, 2001, 9:44:14 AM4/12/01
to
* Paolo Amoroso <amo...@mclink.it>

> I have a design question: why do you keep the code for checking for the
> appropriate balance in a separate :AROUND method instead of adding it to
> WITHDRAW's primary method? I can think of a few reasons:
>
> - because performing a withdrawal and checking for an appropriate balance
> are orthogonal operations
> - for improving modularization, i.e. for making it easier to later add
> other validation methods
> - to emphasize a WITHDRAW protocol

All of the above, some of which I think of only after you suggest them. :)

However, my initial reason for doing this was to show that you might want
to deal with credit limits without modifying the core operation. In real
life, a withdrawal that requests credit is an automatically granted loan,
with a lot of background work to deal with the loan. So a :before method
that took care of the credit approval would update the balance before the
withdrawal updated it again.

Anyone who has had to deal with accounts with real money in real life
knows that the first principle that you never violate is that you never
affect the money supply. Maintaining that invariant is hard work in
banking applications. Much of the complexity in database transactions
come from banking requirements not to create or destroy money, no matter
what happens.

Marco Antoniotti

unread,
Apr 12, 2001, 10:56:38 AM4/12/01
to

Kent M Pitman <pit...@world.std.com> writes:

> Paolo Amoroso <amo...@mclink.it> writes:
>
> >
> > I have a design question: why do you keep the code for checking for the
> > appropriate balance in a separate :AROUND method instead of adding it to
> > WITHDRAW's primary method? I can think of a few reasons:
> >
> > - because performing a withdrawal and checking for an appropriate balance
> > are orthogonal operations
> > - for improving modularization, i.e. for making it easier to later add
> > other validation methods
> > - to emphasize a WITHDRAW protocol
>
> Because if you do override the primary method, you often don't want to lose
> this error checking. And it's MUCH harder to override before, after, and
> around methods than it is to override primary methods. I tend to put
> overridable stuff in the primaries and non-overridable stuff in the
> before/after methods and acts of desperation in the around methods.

I tend to do that too. I really like the "resort to :around methods
as acts of desperation" part :)

I also find myself splitting classes whenever I realize I need some
specific functionality only in :before and :around methods.

Try that with standard OO languages like the "new PL on the block avec
forced indentation rules".

Cheers

--
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group tel. +1 - 212 - 998 3488
719 Broadway 12th Floor fax +1 - 212 - 995 4122
New York, NY 10003, USA http://bioinformatics.cat.nyu.edu
"Hello New York! We'll do what we can!"
Bill Murray in `Ghostbusters'.

Kent M Pitman

unread,
Apr 12, 2001, 11:53:20 AM4/12/01
to
Erik Naggum <er...@naggum.net> writes:

> * Barry Margolin <bar...@genuity.net>
> > Actually, the above example is pretty silly. :before and :after methods
> > are mostly useful in subclasses or mixin classes, to add behavior without
> > totally overriding the primary method that you inherit. Putting the
> > :before method in the same class as the primary method doesn't really
> > make a whole lot of sense -- the error check could just as easily be put
> > in the primary method.
>
> Sigh. In real life, how you deal with withdrawal requests in the absence
> of sufficient funds depends on the account.

Geez, I had thought this was a good enough example that I set it aside to
look at later.

> Add a credit limit, and you need more work, for instance.

I particularly thought the example was clever because such could be
hidden in the withdrawal code, which if it erred would implicitly
signal an error. Accounts could even be cascaded to have this mixin
and it would work. That's not to say that's the one and only one right
way, but it does have some very nice and reasonable properties.

It's not necessary that a bank would use this code for it to look nice
as an example and make the issues clear. Probably no bank would use the
code as given not for this reason but because it uses type REAL, which I
think is wholly unsuitable for money.

Barry also didn't add without-preemption and/or database audit trailing,
but I don't think that hurts anything. And anyway, with a little
thoughtfulness, someone could probably figure out how to make that
work by mixins, too.

> The reaction to such a request is _not_
> integral to the withdrawal process, and conflating the two processes of
> updating the balance and dealing with insufficient funds is really silly,
> because you need to reimplement the core operation (updating the balance)
> in a subclass with different characteristics. That's bad design.

I've known Barry for a long time and he's no idiot, so almost by definition
in my mind, I'd have to say "silly" was probably overstating. He might be
wrong from time to time, but when he is it's rarely for superficial reasons.
I'd like to think that of most of us.

But how about we just ignore that part of your remark and move on to its
substance, which is apparently that you don't like this design. Now you've
got me curious: how would you modularize it? Not for critique, but so we
can collect some alternate examples for style purposes? I think seeing
all of our various points of view will help in a case like this, since I
think style is about choices. The more choices people have, the better
informed their ultimate selection will be in the real situations that come
up (instead of the toy ones we all beat each other up over).

cbbr...@hex.net

unread,
Apr 12, 2001, 12:21:17 PM4/12/01
to
Kent M Pitman <pit...@world.std.com> writes:

That is actually where it would be interesting to extend the example,
to throw in a way of showing it copes well with having multiple
transactions under way concurrently.

>> The reaction to such a request is _not_ integral to the withdrawal
>> process, and conflating the two processes of updating the balance
>> and dealing with insufficient funds is really silly, because you
>> need to reimplement the core operation (updating the balance) in a
>> subclass with different characteristics. That's bad design.

> I've known Barry for a long time and he's no idiot, so almost by
> definition in my mind, I'd have to say "silly" was probably
> overstating. He might be wrong from time to time, but when he is
> it's rarely for superficial reasons. I'd like to think that of most
> of us.

Conflating the processes strikes me as a _controversial issue_; in an
ATM system, it might in fact be reasonable to design the methods to
conflate withdrawal and balance confirmation, as it all has to be done
right at the same time [note that the phrase "done right at the same
time" can reasonably be parsed two ways; I actually intend _both_
meanings :-)].

I'd tend to agree with Erik that it would be preferable to separate
the actions, but just as folks denormalize database tables in real
life to try to improve performance, the "real world" might try to
dictate combining the actions.

> But how about we just ignore that part of your remark and move on to
> its substance, which is apparently that you don't like this
> design. Now you've got me curious: how would you modularize it? Not
> for critique, but so we can collect some alternate examples for
> style purposes? I think seeing all of our various points of view
> will help in a case like this, since I think style is about
> choices. The more choices people have, the better informed their
> ultimate selection will be in the real situations that come up
> (instead of the toy ones we all beat each other up over).

I'd think this to be valuable indeed. Even under the _extreme_
position that Barry's outright _wrong_, and deserves "beating up," he
surely used some vaguely rational criteria to come up with his
approach, and it would surely be valuable to see the fatal flaw in it.

It seems rather more likely to me that Barry's thoughts weren't quite
so fatally flawed; seeing some different positions, and reasons to
distinguish between them, can help people make more informed
selections.
--
(concatenate 'string "aa454" "@freenet.carleton.ca")
http://www.ntlug.org/~cbbrowne/resume.html
Why is it that when you transport something by car, it's called a
shipment, but when you transport something by ship, it's called cargo?

Erik Naggum

unread,
Apr 12, 2001, 1:22:12 PM4/12/01
to
* Kent M Pitman

> I've known Barry for a long time and he's no idiot, so almost by definition
> in my mind, I'd have to say "silly" was probably overstating. He might be
> wrong from time to time, but when he is it's rarely for superficial reasons.
> I'd like to think that of most of us.

What he said was "Actually, the above example is pretty silly", and goes
on to argue that you should do the checking inside the withdraw function.
I'm sorry, but I find it very irritating when someone who obviously has
not paid much attention to what is going on nor shows any interest in
finding out what people have thought has the gall to state that it
_actually_ is "pretty silly". I don't know why Barry does this, but it's
a clear pattern with him: If I suggest something that several people like
or applaud, Barry just _has_ to knock it, sometimes with a bad suggestion
that confuses a lot of people, apparently just to be contrary. I don't
know what this is, but I find it very annoying.

Barry Margolin

unread,
Apr 12, 2001, 2:18:22 PM4/12/01
to
In article <31960849...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
> What he said was "Actually, the above example is pretty silly", and goes
> on to argue that you should do the checking inside the withdraw function.
> I'm sorry, but I find it very irritating when someone who obviously has
> not paid much attention to what is going on nor shows any interest in
> finding out what people have thought has the gall to state that it
> _actually_ is "pretty silly". I don't know why Barry does this, but it's
> a clear pattern with him: If I suggest something that several people like
> or applaud, Barry just _has_ to knock it, sometimes with a bad suggestion
> that confuses a lot of people, apparently just to be contrary. I don't
> know what this is, but I find it very annoying.

I know I'm going to regret this reply, but....

Wow. I know I've been nasty to you in the past, but I hardly thought
"pretty silly" was in the same league; I consider that a relatively
innocuous comment. I didn't say it was wrong, stupid, or anything really
derogatory.

My general feeling is that if you put both a :before/:after/:around method
and a primary method in the same class, you aren't making the most
effective use of the class mechanism to split off the modularity. I
understand why you want the balance checking in a :before method, but I
merely feel that you should then split it off into its own class so that
you can then choose when to mix it in or not. If you have an account with
a credit limit, you would have a different mixin that would check against
the credit limit rather than just the balance.

BTW, unless it was unconscious, I don't think I considered the source when
I wrote my reply. As I've mentioned before, if you didn't have a unique
quoting style, such unconscious behavior would be less likely (if I don't
know it's from you, I can hardly bias my reaction because of it).

Kent M Pitman

unread,
Apr 12, 2001, 2:45:38 PM4/12/01
to
Erik Naggum <er...@naggum.net> writes:

> If I suggest something that several people like
> or applaud, Barry just _has_ to knock it, sometimes with a bad suggestion
> that confuses a lot of people, apparently just to be contrary. I don't
> know what this is, but I find it very annoying.

People often say this of me, as well. Usually in my own case I'm not
trying to knock the original thing but to add an extra viewpoint or
footnote. But it often comes across as my not being satisfied with
the original point of view.

None of us is perfect, Erik. We each have our own trademarked ways
of getting under others' skin. Coping with others' communicational
shortcomings is sometimes how we earn credit toward their willingness
to do the same for us.

Just my opinion.

Besides, what I'm still *really* interested in is hearing how you'd write
the code instead. I hope you'll get to that part...

Erik Naggum

unread,
Apr 12, 2001, 4:59:11 PM4/12/01
to
* Barry Margolin

> As I've mentioned before, if you didn't have a unique quoting style, such
> unconscious behavior would be less likely (if I don't know it's from you,
> I can hardly bias my reaction because of it).

What unique quoting style? If you're trying to reinfoce my impression
that paying attention is not one of your stronger qualities, you're doing
a pretty good job. Much would be improved if you did pay more attention.

Erik Naggum

unread,
Apr 12, 2001, 5:01:23 PM4/12/01
to
* Kent M Pitman

> Besides, what I'm still *really* interested in is hearing how you'd write
> the code instead. I hope you'll get to that part...

I don't follow you. I posted what I thought was the best solution. Then
Barry comes along and calls it "pretty silly", and argues for a different
style. That is, what I consider better or would have written instead has
already been posted. I hope we don't still have that problem with my
articles not propagating properly.

Barry Margolin

unread,
Apr 12, 2001, 5:13:48 PM4/12/01
to
In article <31960979...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
>* Barry Margolin
>> As I've mentioned before, if you didn't have a unique quoting style, such
>> unconscious behavior would be less likely (if I don't know it's from you,
>> I can hardly bias my reaction because of it).
>
> What unique quoting style?

The "* Barry Margolin" attribution style is unique to you, AFAIK. You also
add an extra space after the '>' quoting character. These make your
replies quite distinctive.

> If you're trying to reinfoce my impression
> that paying attention is not one of your stronger qualities, you're doing
> a pretty good job. Much would be improved if you did pay more attention.

It's not a matter of whether I pay attention, it's what I choose to pay
attention to, and "From:" lines are not a high priority to me. I have my
newsreader configured to clear the screen between displaying the header and
the message body, so I can see the maximum amount of message. The header
goes by very quickly and I don't bother looking at the author before
hitting Space to see the message.

Barry Margolin

unread,
Apr 12, 2001, 5:18:14 PM4/12/01
to
In article <31960980...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
>* Kent M Pitman
>> Besides, what I'm still *really* interested in is hearing how you'd write
>> the code instead. I hope you'll get to that part...
>
> I don't follow you. I posted what I thought was the best solution. Then
> Barry comes along and calls it "pretty silly", and argues for a different
> style. That is, what I consider better or would have written instead has
> already been posted. I hope we don't still have that problem with my
> articles not propagating properly.

I didn't think we were having a discussion on the best way to implement
bank software, but rather examples of OO style. I still think that a
:before method in a mixin class is a better example of the power of CLOS's
OO system. Witness that I was not the only one who found it curious that
you put both methods on the same class; I phrased it as "pretty silly"
(which I thought was about as mild a criticism as possible, but you seem to
be conditioned to take offense to anything I write), while the other poster
asked "why?".

Lieven Marchand

unread,
Apr 12, 2001, 1:18:48 PM4/12/01
to
Marco Antoniotti <mar...@cs.nyu.edu> writes:

> Try that with standard OO languages like the "new PL on the block avec
> forced indentation rules".

You really seem to have something against Python. Why?

I'd prefer CL for most applications but it has saved me a few times
from Perl and I find it more readable, maintainable and better
designed than most of its competitors.

--
Lieven Marchand <m...@wyrd.be>
Glaðr ok reifr skyli gumna hverr, unz sinn bíðr bana.

Erik Naggum

unread,
Apr 12, 2001, 5:32:46 PM4/12/01
to
* Barry Margolin

> Witness that I was not the only one who found it curious that you put
> both methods on the same class; I phrased it as "pretty silly" (which I
> thought was about as mild a criticism as possible, but you seem to be
> conditioned to take offense to anything I write), while the other poster
> asked "why?".

I also find it annoying that you have to exaggerate what I take offense
to. If _you_ had asked "why?", there would have been no reason to react
at all, except to answer your question. It is because _you_ seem to be
unable to deal with me that you continue to post derogatory comments. I
don't do that towards you, but you keep doing it towards me. I do not
understand why. That's doubly annoying. I'm asking you to quit it. OK?

Erik Naggum

unread,
Apr 12, 2001, 5:41:46 PM4/12/01
to
* Barry Margolin

> The "* Barry Margolin" attribution style is unique to you, AFAIK. You also
> add an extra space after the '>' quoting character. These make your
> replies quite distinctive.

Previously, it was the | instead of the > that annoyed you so much, and I
fixed that for a number of reasong. Now, it's the *, which has not been
changed. Several other people do that besides me. Lots of people quote
with a space after the >, so that's hardly unique, either. I get the
impression that unless I do everything exactly like you do, you will find
_something_ wrong, and if I did it your way, you would fault me for that,
too. It looks like you're having a personal problem with me, regardless
of what I actually _do_. It's not like you're "after me" or anything
like that, it's simply that it looks very much like you cannot even
_avoid_ finding faults. I find this very annoying. I wish you would
simply stop being so sensitive to what I do. Just get over it, whatever
it is, OK?

Barry Margolin

unread,
Apr 12, 2001, 6:05:55 PM4/12/01
to
In article <31961005...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
>* Barry Margolin
>> The "* Barry Margolin" attribution style is unique to you, AFAIK. You also
>> add an extra space after the '>' quoting character. These make your
>> replies quite distinctive.
>
> Previously, it was the | instead of the > that annoyed you so much, and I
> fixed that for a number of reasong. Now, it's the *, which has not been
> changed. Several other people do that besides me. Lots of people quote
> with a space after the >, so that's hardly unique, either. I get the
> impression that unless I do everything exactly like you do, you will find
> _something_ wrong

Where did I say "annoyed" or "wrong"? Now who's exaggerating the reaction
(something you accused me of in another post)?

I said it was distinctive; although neither feature by itself may be
unique, the combination is probably more limiting, and also I apparently
don't subscribe to the groups where other *-attributors post, because I
can't recall seeing it from anyone other than you. So even though I don't
read From: lines, I can tell they're from you, which opens me up to
subconscious bias.

Erik Naggum

unread,
Apr 13, 2001, 7:57:19 AM4/13/01
to
* Barry Margolin

> So even though I don't read From: lines, I can tell they're from you,
> which opens me up to subconscious bias.

Work on it, will you?

Dave Pearson

unread,
Apr 14, 2001, 3:03:15 AM4/14/01
to
* Barry Margolin <bar...@genuity.net>:

> My general feeling is that if you put both a :before/:after/:around method
> and a primary method in the same class, you aren't making the most
> effective use of the class mechanism to split off the modularity.

What if there isn't a good reason for such splitting?

As an example, I've been toying around with an NNTP client class in CL, by
way of having some fun in CL. A couple of the methods that do the talking to
the NNTP server ensure that there is a connection in place and throw an
error if not. I'd not considered a :before method for doing such a check
until I saw Erik's post. I changed the code to work that way and it actually
seems to make more sense like that.

Now, I suppose there could be an argument for writing a base "NNTP with no
connection checks" class and then do that :before checking in a "NNTP with
connection checks" class but I can't really see the point in that.

I can, however, see the point in having a base class that does the
connection checking which simply throws an error if the connection isn't
there, while having a sub class that re-makes a connection if the connection
has been lost.

I did see mention that overriding :before behaviour is tricky so I've made a
mental note to look into this but I think the important point here is that
Erik's example, from my point of view anyway, wasn't silly, it was very
illustrative. Using :before in sub class is an obvious thing but for some
odd reason I'd never considered the use of them in the "same class" as a
method of implementing pre or post checks (for example).

IOW, as I read it, I don't think the example was supposed to make "the most
effective use of the class mechanism". Even if it was and it didn't it did
illustrate a useful point, at least for one reader of this group.

--
Dave Pearson: | lbdb.el - LBDB interface.
http://www.davep.org/ | sawfish.el - Sawfish mode.
Emacs: | uptimes.el - Record emacs uptimes.
http://www.davep.org/emacs/ | quickurl.el - Recall lists of URLs.

Tim Bradshaw

unread,
Apr 16, 2001, 8:46:58 AM4/16/01
to
* Barry Margolin wrote:

> The "* Barry Margolin" attribution style is unique to you, AFAIK. You also
> add an extra space after the '>' quoting character. These make your
> replies quite distinctive.

This quote was what my newsreader did. I think I hacked it to produce
the citing style (but so long ago I can't remember), I don't think I
hacked the quoting char stuff.

--tim

Tim Bradshaw

unread,
Apr 16, 2001, 9:00:39 AM4/16/01
to
* Barry Margolin wrote:
> I didn't think we were having a discussion on the best way to implement
> bank software, but rather examples of OO style. I still think that a
> :before method in a mixin class is a better example of the power of CLOS's
> OO system. Witness that I was not the only one who found it curious that
> you put both methods on the same class; I phrased it as "pretty silly"
> (which I thought was about as mild a criticism as possible, but you seem to
> be conditioned to take offense to anything I write), while the other poster
> asked "why?".

Trying to drag this back on topic... I think that although it's
perhaps a `better example of CLOS' to have non-primary methods and
mixins together, they can be useful in a single class framework too.
I use :before and :after methods for things that need to be done but
are not part of the main `normal' bit of the code. I find this makes
things easy to read, because the primary method can just assume that
everything is OK. So rather than:

(defmethod foo ((x bar))
(boring-checking-code x)
(more-boring-code x)
(prog1 (tiny-useful-bit-of-code x)
(yet-more-rubbish x)))

I write:

(defmethod foo :before ((x bar))
(boring-checking-code x)
(more-boring-code x))

(defmethod foo ((x bar))
(tiny-useful-bit-of-code x))

(defmethod foo :after ((x bar))
(yet-more-rubbish x))

I suppose the OO purist would argue that I should have mixin classes
that do the checking stuff. Perhaps so.

--tim

Erik Naggum

unread,
Apr 16, 2001, 10:00:19 AM4/16/01
to
* Tim Bradshaw <t...@cley.com>

> (defmethod foo ((x bar))
> (boring-checking-code x)
> (more-boring-code x)
> (prog1 (tiny-useful-bit-of-code x)
> (yet-more-rubbish x)))

You may want to use multiple-value-prog1 here, which is a gratuitous
invasion of multiple value. prog1 should have preserved multiple values
to begin with, just like :after methods, unwind-protect, etc, do. This
is but another reason to use :after methods.

0 new messages