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

Testing for function equality

7 views
Skip to first unread message

Matthew X. Economou

unread,
Jun 1, 2002, 8:25:43 PM6/1/02
to
Can one test the contents of two places for functional equality (that
they point to the same FUNCTION object) in conforming code?

Here's what I want to do. Section 2.4.2 "Right-Parenthesis" of the
Common Lisp specification states in part:

The right-parenthesis is invalid except when used in conjunction
with the left parenthesis character.

This is re-enforced by the following text from the function
specification for SET-SYNTAX-FROM-CHAR in section 23.2 "The Reader
Dictionary":

A macro definition from a character such as " can be copied to
another character; the standard definition for " looks for another
character that is the same as the character that invoked it. The
definition of ( can not be meaningfully copied to {, on the other
hand. The result is that lists are of the form {a b c), not {a b
c}, because the definition always looks for a closing parenthesis,
not a closing brace.

I'm trying to write reader macros for #\( and #\) that ignore this
particular restriction. My first try for writing the pair of macros
involved creating a new dynamic environment in each invocation of the
left parenthesis reader macro. When recursive calls to READ invoked
the right parenthesis reader macro, the macro would check for this
dynamic environment. If it existed, it would return a special value
that would indicate the end of the list. Otherwise, it would signal
an error.

Unfortunately, this doesn't work properly in the error case of parsing
the following kind of input:

(a1 b2 . c3 d4)

The left parenthesis reader macro should signal an error when it
notices that the token following C is not a right parenthesis. My
functions would incorrectly read the "d4" token and then throw the
error. Since it doesn't seem possible to unread a token after READ
has parsed it, I need to find a different way of closing the list.

In my second implementation, the reader macro for right parenthesis
only signals an error if read. When the left parenthesis reader macro
peeks at the next character in the stream, it could look up the reader
macro function for that character as if by GET-MACRO-CHARACTER. If
the function is the same as the reader macro for right parenthesis,
then it could end the list. If not, it could continue recursively
reading objects or signal a syntax error, as appropriate.

So, can one test the contents of two places for functional equality
(that they point to the same FUNCTION object) in conforming code?

--
Matthew X. Economou <xeno...@irtnog.org> - Unsafe at any clock speed!
I'm proud of my Northern Tibetian heritage! (http://www.subgenius.com)

Erik Naggum

unread,
Jun 2, 2002, 5:43:08 AM6/2/02
to
* "Matthew X. Economou"

| I'm trying to write reader macros for #\( and #\) that ignore this
| particular restriction.

See the function read-delimited-list. You appear seriously confused as
to how the reader collects lists and terminates the reading. There is no
point in writing a new "general" reader macros for this -- just ensure
that you pass the right character to read-delimited-list in your reader
macro function.
--
In a fight against something, the fight has value, victory has none.
In a fight for something, the fight is a loss, victory merely relief.

70 percent of American adults do not understand the scientific process.

Matthew X. Economou

unread,
Jun 2, 2002, 2:35:04 PM6/2/02
to
>>>>> "Erik" == Erik Naggum <er...@naggum.net> writes:

Erik> See the function read-delimited-list. You appear seriously
Erik> confused as to how the reader collects lists and terminates
Erik> the reading. There is no point in writing a new "general"
Erik> reader macros for this -- just ensure that you pass the
Erik> right character to read-delimited-list in your reader macro
Erik> function.

I must not have communicated my intent properly. I am looking to (1)
create a generic solution that is copy-able via SET-SYNTAX-FROM-CHAR
and to (2) extend the Lisp reader so that the following two sequences
of input to a Lisp READ-EVAL-PRINT loop have the same syntax:

(let ((foo bar)
(baz qux))
...)

(let [(foo bar)
(baz qux)]
...)

Using READ-DELIMITED-LIST won't accomplish this. Instead, I must
modify the reader. The Common Lisp specification states that one
cannot meaningfully copy the reader macro function of #\( because it
is hard coded to look for #\) to terminate the list. I would like to
write a version of the left parenthesis reader macro function that can
be meaningfully copied, provided one copies the reader macro function
for #\) as well.

Given a function DOT-CHAR-P, which tests a character for the "dot"
constituent trait in the current readtable, I've written the following
reader macros for #\( and #\):

(defun reader-macro-left-parenthesis (stream char)
(let ((new-list nil)
(new-list-last-cons nil))
(loop
(let ((next-char (peek-char t stream t nil t)))
(cond
((dot-char-p next-char)
;; Read in the cdr of the cons cell and terminate the list.
;; If the next non-whitespace character following the cdr is
;; not the end-of-list token, signal an error.
(read-char stream t nil t) ;skip over the dot token
(setf (cdr new-list-last-cons) (read stream t nil t))
(unless (eq (get-macro-character (peek-char t stream t nil t))
(get-macro-character #\)))
(error ...))
(read-char stream t nil t) ;skip over the end-of-list token
(return new-list))
((eq (get-macro-character next-char)
(get-macro-character #\)))
;; Terminate the list.
(read-char stream t nil t) ;skip over the end-of-list token
(return new-list))
(t
;; Append the next object to the end of the list. Store the
;; new end of the list for the next append operation. If
;; this is the first object accumulated, initialize the
;; list.
(let ((new-cons (cons (read stream t nil t) nil)))
(if (null new-list)
(setf new-list new-cons)
(setf (cdr new-list-last-cons) new-cons))
(setf new-list-last-cons new-cons))))))))

(defun reader-macro-right-parenthesis (stream char)
(error ...))

Using these functions in place of the standard reader macro functions
allows one to meaningfully copy the syntax of #\( to a new
list-opening character, provided one also copies the syntax of #\) to
a corresponding new list-closing character.

I want a straight answer to the question: Can EQ test two functions
for equality in conforming code code? The specification pages for EQ
and family don't say. The above code depends on the answer being
"Yes."

Coby Beck

unread,
Jun 2, 2002, 5:36:09 PM6/2/02
to

"Matthew X. Economou" <xenopho...@irtnog.org> wrote in message
news:w4or8jp...@eco-fs1.irtnog.org...


> I want a straight answer to the question: Can EQ test two functions
> for equality in conforming code code? The specification pages for EQ
> and family don't say. The above code depends on the answer being
> "Yes."

CL-USER 1 > (setf foo #'car)
#<function CAR 200E2AF2>

CL-USER 2 > (eq #'car foo)
T

but I don't know what you're really getting at, not having studied your
code. This answers the question as I understand it. If you mean equal as
in having the same semantics, that seems like a tall order!

--
Coby Beck
(remove #\Space "coby 101 @ bigpond . com")


Erik Naggum

unread,
Jun 2, 2002, 6:30:48 PM6/2/02
to
* "Matthew X. Economou"

| Using READ-DELIMITED-LIST won't accomplish this.

Sigh. Yes, it will. (I really wonder why you ask for help when you
reject the offers you get. What is _wrong_ with people who ask for help
in such a manner that only the single, specific question they ask may be
answered? If you got stuck, do you think it is because you made all your
other choices as wisely and informedly as possible? Of course not! You
are stuck _now_ because you made a critical error a _long_ time ago. The
ability to make yourself aware of the choices you have made is crucial to
learn from experience. Lack of such ability is goddamn annoying to those
who watch you fumble and stumble through a wilderness of non-solutions
instead of going straight for the right answer when given a hint.)

| Instead, I must modify the reader.

You only think you must. Please listen.

| The Common Lisp specification states that one cannot meaningfully copy
| the reader macro function of #\( because it is hard coded to look for #\)
| to terminate the list.

Yes, it calls read-delimited-list with #\). This is _really_ obvious.

| I would like to write a version of the left parenthesis reader macro
| function that can be meaningfully copied, provided one copies the reader
| macro function for #\) as well.

This is the wrong approach. How do you know which terminating delimiter
you want to associate yourself with? How do you communicate this? Why
are you so dead set against communicating it directly to the function
that reads the delimited list?

| Using these functions in place of the standard reader macro functions
| allows one to meaningfully copy the syntax of #\( to a new list-opening
| character, provided one also copies the syntax of #\) to a corresponding
| new list-closing character.

If you want to arrive at a solution, rather than your own preconceived
solution, which you are now trying to force to work, it is no harder than
to make a function that accepts two arguments, the delimiting characters,
and sets up the reader for the former macro character to be a function
that calls read-delimited-list with the latter character as terminator,
and then copies #\) to the latter so a stray terminator will signal an
error.

I posted code only yesterday that used <> and () for lists. Do you think
I mucked around with writing my own read-delimited-list to get this
effect? No. It is simple and straightforward with read-delimited list.

| I want a straight answer to the question: Can EQ test two functions for
| equality in conforming code code? The specification pages for EQ and
| family don't say. The above code depends on the answer being "Yes."

You _want_ a straight answer? Really? Are you sure you understand how a
voluntary forum works? Why are you so inconsiderate? How hard can it be
to treat people who have expressed a desire to _help_ you nicely?

Geez, the clueless newbies here are getting more arrogant by the minute.

You can do the work to figure out the "straight answer" yourself. The
answer is right there in front of your pertinacious obstinateness.

Paul Foley

unread,
Jun 2, 2002, 9:39:43 PM6/2/02
to
On 02 Jun 2002 14:35:04 -0400, Matthew X Economou wrote:

>>>>>> "Erik" == Erik Naggum <er...@naggum.net> writes:
Erik> See the function read-delimited-list. You appear seriously
Erik> confused as to how the reader collects lists and terminates
Erik> the reading. There is no point in writing a new "general"
Erik> reader macros for this -- just ensure that you pass the
Erik> right character to read-delimited-list in your reader macro
Erik> function.

> I must not have communicated my intent properly. I am looking to (1)
> create a generic solution that is copy-able via SET-SYNTAX-FROM-CHAR
> and to (2) extend the Lisp reader so that the following two sequences
> of input to a Lisp READ-EVAL-PRINT loop have the same syntax:

> (let ((foo bar)
> (baz qux))
> ...)

> (let [(foo bar)
> (baz qux)]
> ...)

> Using READ-DELIMITED-LIST won't accomplish this.

Why not? ISTM something like

(defun read-list (stream char)
(read-delimited-list (case char (#\( #\)) (#\{ #\}) (#\[ #\])
(#\< #\>) (otherwise char))
stream t))

does exactly what you're asking for, doesn't it?

> modify the reader. The Common Lisp specification states that one
> cannot meaningfully copy the reader macro function of #\( because it
> is hard coded to look for #\) to terminate the list.

In other words, it can be written as (read-delimited-list #\) ...)

> Using these functions in place of the standard reader macro functions
> allows one to meaningfully copy the syntax of #\( to a new
> list-opening character, provided one also copies the syntax of #\) to
> a corresponding new list-closing character.

So something like '[a b {c d (e] f) g} should be legal input?

--
You don't have to agree with me; you can be wrong if you want.

(setq reply-to
(concatenate 'string "Paul Foley " "<mycroft" '(#\@) "actrix.gen.nz>"))

Matthew X. Economou

unread,
Jun 2, 2002, 11:39:57 PM6/2/02
to
>>>>> "Erik" == Erik Naggum <er...@naggum.net> writes:

Erik> Yes, it calls read-delimited-list with #\). This is
Erik> _really_ obvious.

Not obvious to me. Thanks for the pointer though.

Erik> You _want_ a straight answer?

You are absolutely correct in that this was worded strongly. My
apologies.

Matthew X. Economou

unread,
Jun 2, 2002, 11:43:13 PM6/2/02
to
>>>>> "Paul" == Paul Foley <myc...@actrix.gen.nz> writes:

Paul> So something like '[a b {c d (e] f) g} should be legal
Paul> input?

Ah, I now see how I was being dense. It probably shouldn't be legal
input, hence the combination of ECASE and READ-DELIMITED-LIST.

Sorry to waste all of your time. I'll head back to lurking.

Tim Moore

unread,
Jun 3, 2002, 1:27:41 AM6/3/02
to
On Sun, 02 Jun 2002 22:30:48 GMT, Erik Naggum <er...@naggum.net> wrote:
>* "Matthew X. Economou"

>| The Common Lisp specification states that one cannot meaningfully copy
>| the reader macro function of #\( because it is hard coded to look for #\)
>| to terminate the list.
>
> Yes, it calls read-delimited-list with #\). This is _really_ obvious.

Not quite. read-delimited-list doesn't handle dotted list notation.

Tim

0 new messages