Re: Macro Question: Paraphrasing



drewc wrote:

>I still don't see what you are getting at. If your problem is the
>ordering of arguments, why not use keywords for everything?

>(unzip :files-listed-in ticket :from zipfile)

Now, you're just being difficult. Why not use keywords for everything?
Talk about mantra-chanting!

You've conveniently ignored my subsequent explanation (with example)
that keywords can distort the meaning of a symbol on the surface level,
which is the language used by the human reader to map symbols to
concepts. You ignored my example here, when I explained clearly why
that would foul up the function definition, so that you could fight it
to the bitter end. When you finally address the example, you ignored
the obvious, and instead complained about me not naming functions with
an imperative verb. Whereas you can accept using the preposition :from
in the body of the function definition to refer to the noun
zipfile--which would suggest that you're just mentally mapping symbols
to objects--you can't accept that I've chosen another convention,
because I want to write (setf buffers (to (unzipped (files-listed-in
ticket) (from zipfile))) instead of (setf buffers (unzip
:files-listed-in ticket :from source). Do you really not understand my
position? Or are you just a Lisp bully?

>or if you really want to be specific at the call site, create a new
>(possibly local) function UNZIP-USING-TICKET. Again, i'm still missing
>the point entirely. UNZIP is a function which unzips files right? What
>is a ticket? what does it have to do with unzipping files?

What is a ticket? Are you really that dense? WTF? :files-listed-in
what? :files-listed-in list? :files-listed-in shopping-list?
:files-listed-in ticket? Who cares if it's a list or a (make-instance
'ticket) containing a list of files that the caller wants to be
UNZIPPED from the zipfile.

If you use Linux and KDE, Konqueror gives you access to archives. In
Windows, My Computer and Explorer both do the same. Each file manager
allows you to copy individual files from an archive. Do the file
managers decompress all of the files in the archive just to copy a
single file chosen by the user? Given a large archive, that could take
much longer than necessary.

You go into a diner. The server comes to your table and writes down
your order. Does the kitchen prepare everything on the menu to give you
what you ordered? Of course not! The diner wouldn't be in business for
very long. The server gives a TICKET to someone in the kitchen, and a
cook prepares only what's listed on the ticket!

I found a zip library written by someone. I'd like to use that library,
or at least parts of it, without restricting myself to writing
unreadable code. The original UNZIP function has no concept of
extracting individual files from a zipfile. Using UNZIP-USING-TICKET
requires that I add another function to the interface of the core of
the library, and it still forces me to refactor the library, because
the original author decided that UNZIP would extract all of the files
in an archive.

Are you familiar with grep? If you want grep to search
case-insensitively, do you call with-case-insensitive-matching-grep
'foo' *? I'm glad the authors decided instead to let us specify grep -i
'foo' *!

If I rename unzipped to %unzipped and define paraphrases:

(paraphrase (unzipped (files-listed-in ticket) (from zipfile) (to
target-path))
(to (%unzipped zipfile ticket target-path)))

(paraphrase (unzip (files-listed-in ticket) (from zipfile) (to
target-path))
(to (%unzipped zipfile ticket target-path)))

(unzip (from zipfile) (to target-path))
--> (%unzipped zipfile NIL target-path)

(unzipped (from zipfile) (to target-path))
--> (%unzipped zipfile NIL target-path)

(unzip (from zipfile) (files-listed-in ticket))
--> (%unzipped zipfile ticket NIL)

(unzipped (from zipfile) (files-listed-in ticket))
--> (%unzipped zipfile ticket NIL)

(unzip (from zipfile) (files-listed-in ticket) (to target-path))
--> (%unzipped zipfile ticket target-path)

(unzipped (from zipfile) (files-listed-in ticket) (to target-path))
--> (%unzipped zipfile ticket target-path)

With two paraphrase, I have six functions. As with keywords, I can call
the functions with the arguments in any order. Unlike keywords, I don't
pollute the function definition with noise. Sure, with a slightly
different paraphrase macro, I could instead form the paraphrases with
keyword syntax, as follows:

(paraphrase (unzipped :files-listed in ticket :from zipfile :to
target-path))
(to (%unzipped zipfile ticket target-path)))

(paraphrase (unzip :files-listed in ticket :from zipfile :to
target-path))
(to (%unzipped zipfile ticket target-path)))

This still doesn't pollute the function definition, and I might find
good reasons to do it this way, e.g., namespace pollution. However,
specifying the cues in lists would be consistent with macros for
eliding these cues in cases for which I don't need full paraphrases.

>> This relates to one of the many complaints I have about Java....

> I don't see how this is related at all.

Now, you're just being ridiculous--or you have the I.Q. of a snail. Do
you mean to tell me that you can't relate hiding the most significant
information in Java code and javadocs by not putting the most
significant information first to hiding the most significant
information in a function call by not putting the most significant
argument first? I answered your question directly and elaborated, in
order to clarify my reasoning. Short attention span? ADD? ADHD? What?
Or are you just having fun egging me on?

> Which arbitrary order? you don't have to order keywords.

KEYWORDS DON'T GIVE ME THE EXPRESSIVENESS I WANT AT THE CALL SITE *AND*
IN THE FUNCTION DEFINITION!!!!!!!!

> If you are not
> using keywords, i might agree that for some functions, the arbitrary
> order is a hassle (GETF and GETHASH always mess me up)

THANK YOU! That is exactly my point.

> but i certainly
> would not want to type (cons :car 'a :cdr b) , nor read it.

Your example is completely contrived. A CONS is an ordered collection:

* (first (cons 'a 'b))

A
* (car (cons 'a 'b))

A
* (rest (cons 'a 'b))

B
* (cdr (cons 'a 'b))

B

It's the basic building block of the Lisp language. CAR and CDR add
more maps, for historical reasons. It doesn't require any more mental
mapping. (cons 'a 'b) doesn't cause any confusion unless your native
language is by convention read right to left. I don't accept the notion
that I need a new map for every single function of every single
library, just to maintain some kind of mathematical purity, when my
native language (which is usually mapped onto the code with SYMBOLS)
could provide a direct map to the semantics if the code gave me enough
CONNECTIVE cues.

> How does PARAPHRASE help here?

Have I not clarified it yet? One paraphrase *effectively* remapped the
function to the imperative verb, *effectively* obviated the need to
write three different DEFUNs, got rid of those NILs at the call, which
you so desperately despise, and effectively provided keywords, which
you can specify in any order, without fouling up the expressiveness of
the function definition with :keywords which map to the surface level
but not to the definition level, because the Lisp keywords serve as
placeholders for the arguments instead of connectives... IN TWO LINES
OF CODE! What more do you want?

>Most of your function names make no sense to me. why 'unzipped' and
>'extracted-files'? Perhaps the reason i have trouble understanding what
>it is you are looking for because intent is not clear from your code.

Oh, jeez! Here we go! What is so difficult to understand about (setf
buffers (to (unzipped (files-listed-in ticket) (from zipfile)))). It's
perfectly NATURAL and maps directly from the surface level (English) to
the concept: "Set buffers to the unzipped files listed in the ticket,
from the zipfile." Yay, Lisp!

>I have no problem reading function lambda-lists, so your "problem with
>readability" is only subjective.

Guess what! I have relatively little problem reading lambda lists
either. My problem with the readability of code I've seen is DIRECTLY
related to your problem with GETF and GETHASH. It requires mapping a
symbol order specified by someone else to the concepts which the
functions encapsulate, precisely because the specification doesn't
provide any connectives to cue the reader to the semantics of the form.
If you want to map hundreds of forms to hundreds of concepts because
the specifications don't provide the information necessary to map it
directly from the surface level of the forms, that is your prerogative.
It's a waste of energy. I want to concentrate on the problems, not on
mapping form to meaning.

We already have the maps, but formal languages pull the rug out from
under us.

>How does the keyword definition 'foul' the lambda list? What do you
>propose as an alternative?

OH, PUHLEAZE! Do you mean to tell me that you don't see anything weird
in the example I gave:

>(when (and to (or (pathname-name to) (pathname-type to)))
> (error "The target is not a directory or lacks a trailing slash."))

(and to...

To what?

(or (pathname-name to...

To what?

(pathname-type to...

To what?

I chose keywords to clarify the meaning on the surface level at the
function call, and because Lisp keywords in lambda lists are
placeholders, instead of connectives, the surface meaning changed from
the function call to the lambda, where the surface level is almost
meaningless.

Instead of the prepositions to and from, I could have chosen nouns.

(defun unzip (&key ticket source path)...)

Of course, that cleans it up for the lambda, but what does it do to the
function call?

(let ((ticket ...)
(target ...)
(zipfile ...))
(unzip :ticket ticket :target target :zipfile zipfile))

Or even_

(progn
(unzip :ticket (("context.xml")) :zipfile "opus.sxw" :target
"target-path"))

That's ridiculously redundant in either case, and it fouls up the
surface form. I don't want to unzip the TICKET. I want to unzip the
files-listed-in TICKET.

(unzip :files-listed-in ticket :from zipfile :to target)

and

(unzip (files-listed-in ticket) (from zipfile) (to target))

say exactly what I mean to say. But if the DEFUN uses the keywords in
the former, it makes a mess. The latter should be much easier for the
human reader, because it groups the connective with the argument.

>The only problem i had with mapping the code above to what it should do
>was deciphering your function naming convention.

GOOD GRIEF, CHARLIE BROWN! On the surface, you can map the preposition
to the object, but you can't map a sentence specifying that I want the
UNZIPPED files-listed-in the ticket from the zipfile. You seem to have
no problem with the preposition mapping to the object of the
preposition, effectively eliding the nominative, which would convey
more meaning within that lexical environment. So why can't you map the
imperative to the noun phrase UNZIPPED file-listed-in ticket from
zipfile, which is what I really want when I have a ticket.

>You are complaining
>about having problems reading code and documentation, and here you are
>naming functions after what they return rather than what they do

Oh! And (car foo) cars foo, but (cdr foo) cdrs it. IIRC car and cdr
were the NAMES of the registers, Content Address Register and Content
Decrement(?) Register. And I suppose (first bar) firsts bar and (rest
bar) rests it. Does (second baz) second it?

> (if i'm
>mistaken about what those functions do, please correct me, but my point
>about it not being clear stands)... that's just odd. It's like renaming
>a MURDER function to CORPSES .. how does that convey to the reader what
>the function is doing. Functions are verbs!

They are? I don't see that anywhere in the specification, and a lot of
coders would disagree with you. In addition to the examples above, we
also have_

(defclass foo ()
((bar :accessor bar)))

(setf (bar foo) 'baz)

(bar foo) --> 'baz

The accessor method (a generic function) specifies what it returns.
Your assertions are ridiculous, and your logic based on these
mind-numbing assertions is faulty. How old are you? 12?

>What 'mapping' are you refering to? I'm probably one of those who find
>it natural, because i can't seem to see what your problem is. Then
>again, i've programmed a fair bit of CL and am used to reading it.

And I've written and read a ton of Java and C/C++ code, and I will
NEVER be used to it. It's insane to constantly remap forms to concepts
when language can map it directly on the surface. A symbol can only
point to something. If I ask you what the moon is, you can only point
to it. But language can do it on the surface level. Stop working for
the computer, and make the computer work for you.

>It's not that i don't like it, its just that i can't seem to grasp what
>it is you are trying to do, and why. Can you explain what your
>PARAPHRASE macro does, and what 'eliding semantic cues' is.

That all depends on what the definition of is is. The connectives
clarify the meaning. The compiler can munge the connectives from the
surface form and still have all of the information for the underlying
functional form. When I tell the compiler to (elide-cue to), the
compiler will elide (omit) the semantic cue, which contains meaning on
the surface level but is meaningless to the compiler on the functional
level.

>This is the problem i have with your 'paraphrase' operator .. why do you
>want to reorder the arguments of existing functions when you can simply
>define new functions with whatever wacky ordering you want?

With the paraphrase example above, I effectively defined three
functions with one paraphrase, in two lines instead of three defuns.
That's at least a 3:1 compression without loss of meaning.

>Your idea
>seem to be to create a bunch of functions with the same name that have
>different functionality ... why? how does this improve readabilitiy?

It compresses information. Whether I want to unzip only the files
listed on a ticket or the entire file, I still want to UNZIP something.
If Lisp will let me say (unzip (files-listed-on ticket) (from zipfile)
(to path)) and (unzip (all-files-in zipfile)) by specifying two lines
of code instead of 12, and I can do this in any case that makes code
easier for me to comprehend, then why shouldn't I use that power.

>Ah, i see, you're one of those.

Yeah, I'm one of those [weirdos].

> I was not aware that you were creating a
> new language here,

We've discussed different ways to add on to Lisp. That's creating a new
language in itself, so it was obvious. Whether I'm only enhancing Lisp
or I'm creating an entirely new language, I'm creating a new language
in either case. Every single computer program for which I have reviewed
the source code has created a new language but failed to map the
concepts directly.

If I was fluent in the languages, I could compose these c.l.l. posts in
Spanish or Latin and probably not lose any information in the
translation. Would you understand it? However, programming languages
map concepts with huge losses in information on the surface level, in
the human interface. I am working on that problem.

>i simply thought you were trying out common lisp.

Why should my motives affect the discussion.

>Common Lisp is a great environment for experimenting in language design.

Of course, it is, or I wouldn't be looking at using it.

>And yet you are advocating yet-another-language of your own creation,
>which not only forces me to learn a library

Whoa! I haven't forced anything on anyone. In the original post, I only
asked if other people had used Lisp to do what I described and how they
would do it. I had some difficulty with some macro concepts, and others
simplified it for me. You started egging me on, so I decided to defend
my reasoning. I think I have explained myself very coherently. I doubt
that paraphrasing as I defined it will become part of the standard. I
don't expect that it will start showing up in every project I see on
the internet. If it does, so what? You'll have to learn a new concept,
which is a lot easier than the scads of concepts you need to remap to
understand code in its present form.

There is no library. I defined a mechanism for rephrasing forms in a
way I haven't seen elsewhere. I thought Lisp was first about List
Processing. That's all I'm doing.

> (which slime makes easy ...
>i shows you the name and order of the arguments as you type ... how is
>that hard?),

Hmmm... Yet you still have trouble with GETF and GETHASH.

Sure, SLIME is neat. It adds some nice functionality to Emacs. But I
still haven't determined how to copy and paste from XEmacs to other
programs. I still haven't determined how to tab from the directory
widget to the file widget in the file dialog without taking my hands
off of the keyboard, and I can't find this information documented
ANYWHERE. XEmacs doesn't use a standard interface, so I have to remap
concepts again. CTRL-C no longer means copy. CTRL-V no longer means
paste. It's a klucking fudge. So I don't always use XEmacs + Slime to
read or write code.

>but an entirely new language with a compiler written in
>itself that only one programmer on earth knows how to maintain!

Lisp was new at one time. Lisp was new to you at one time. Lisp has
more than one implementation with more than one programmer who knows
how to maintain it.

Java was new at one time. Java has more than one programmer who knows
how to maintain it.

C, C++, Python, Perl, etc., were all new at one time. Some of them have
more than one implementation. Most of them have more than one
programmer on earth who knows how to maintain it.

Knowledge isn't proprietary. It grows. It spreads.

There is more than one programmer on earth.

I think I've dispelled another one of your fallacies.

This new language and this new compiler don't even have full
specifications. I haven't even described this new language and this new
compiler, and already you've cast it aside. That's on you, Bub.

>Fair enough, although i wouldn't want you on my team!

I would presume that the feeling is mutual.

>When i write code,
>i want the reader, who i almost always assume will not be me, to be able
>to read the code without having to struggle with weird contructs of my
>own creation.

That's bull***. Any code you write will create new constructs. If the
new constructs don't map directly to prior known constructs, the reader
will need to work harder to create those maps. Just because my
preferred style doesn't follow convention doesn't make this style
unreadable. Just because these new constructs that I have defined don't
follow those used by the herd doesn't mean that these new constructs
aren't useful. These concepts map more directly to common knowledge.
Whereas they don't map directly to common Lisp usage, they'll require
less effort to use than other types of mappings.

>I tend to only use two types of macros. WITH-* and DEF-*,
>and i comment very clearly when doing something hairy or tricky.

La-ti-da.

>Again .. why didn't you just define your own function

I defined six new signatures in 5 lines. I could probably compress it
further without any loss of information. Two lines per DEFUN with a
space between each would total 17 lines. Each PARAPHRASE only
paraphrase the function, so it won't break existing code. The keywords
are no longer placeholders instead of connectives... The list of
reasons just keep growing.

>.. why the desire
>to change someone elses?

Hell is other people--Sartre, I believe,

>DEFUN is a lot easier to learn than DEFMACRO,

Oh, in that case, let's not use any macros anymore. As a matter of
fact, let's not use anything based on macros, and we can throw out a
large part of the standard library and the functionality of lisp. Deal?

>and both make more sense to me than PARAPHRASE.

I apologize. What was I ever thinking when I decided to foist this
monstrosity onto the world? Oh, wait. I didn't. I only asked for ideas
about how to go about it.

Have you never paraphrased what someone else said in order to add
clarity to the message?

>> arguments, because I know that I don't need to extract all of the files
>> from an OpenDoc document to process what I need from it.

>Ah .. that's what a 'ticket' is ? a list of files? why not a new
>function EXTRACT-FILES-FROM-ARCHIVE or UNZIP-FILES?

But %UNZIPPED already does that! And with the paraphrases, you don't
need to know anything about how it does it.

>Ok ... why not READ-OPEN-OFFICE-FILE ? why should i, the reader, care
>that the file is just a zip file .. abstraction is the key here. Why are
>you trying to take a function called UNZIP and turn it into a function
>that reads OO.o documents? If you are trying to accuratly convey
>information to the reader, choosing the right name, and having small
>functions with simple behavior, will go a lot farther than having a
>function with a single name that has as many different behaviors as
>there are uses for zip files.

Now wait just a cotton-pickin' minute! Your tangent assumes that I
haven't defined such a function for the abstraction (though I surely
wouldn't choose such a name for the function). You have absolutely no
evidence to support such an assumption. How does mentioning the desire
to parse OpenBook documents lead to the conclusion that I wouldn't make
such an abstraction? I only mentioned that the OOo file was a zipfile
in the context of extracting a single file from an archive.

>You know, you could factor out the common code into a function that is
>used by all three. Then you wouldn't have to write the same code
>everywhere.

I believe I already mentioned considering the possibility. However, the
PARAPHRASE does very nicely hide the implementation details. At the
moment, I can't see any reason to define three different function when
I bought the same with one paraphrase in two lines.

>But how does your macro fix that? now i only have to remember one name,
>but a possible infinite number of behaviors?

You don't have to do any such thing! It's no more complicated than
calling a specialized method! And I didn't need to define three
different methods!

>I'd rather see
>READ-OPENDOC-FILE than try to figure out that the UNZIPPED(!?) function
>is also used, when called in some strange manner, to open OO.o files.

As I already made painfully clear, it would require no such thing,
because you JUMPED to the WRONG conclusion.

>Why should entirely different actions have the same interface?

So to search for string in a directory, without regard to case, should
require

~ $ ignoring-case-grep 'foo' *

instead of

~ $ grep -i 'foo' *

If I want it to report line numbers

~ $ reporting-line-numbers-ignoring-case-grep 'foo' *

instead of

~ $ grep -in 'foo' *

If I want to search recursively

~ recursively-reporting-line-numbers-ignoring-case-grep 'foo' *

instead of

~ $ grep -inr 'foo' *

With paraphrasing and compiler-elided cues, I have a complete
expression (with semantic cues) at the function call and a lot of
compression on top of that!


>Following
>that to it's logical conclusion, the entire language should be
>consolidated into a single operator. We can just pass lists of code to
>that function, with maybe, say, the first item in the list denoting a
>function, and the rest arguments to that function... Wow ... we've just
>invented EVAL :)

Following your logic to the extreme, we shouldn't specialize any
methods which have very similar semantics, and we shouldn't name
anything with the same name, function, value or otherwise, in any
context whatsoever.

>So .. why not use methods? There is already a great generic function
>system in common lisp!

I don't need methods here. The problem doesn't require run-time type
checking to dispatch the function. I have three different functions
with very similar semantics. It uses a consolidated interface and
paraphrases to hide the details.

>not really. You've pointed out that you have a problem with keywords,
>but you have not, to my satisfaction, been able to convey precisely what
>those problems are, nor have you been able to explain how your idea
>fixes them.

I don't know how I could have been more clear about it. Lisp keywords
in functions serve as placesholders instead of connectives. I offered
an elegant solution, but you're stuck on using the keyword kludge.

>What information are you adding? I still don't understand the point of
>what you are trying to do here.

You're not even trying. You must think that people should just use
whatever maps someone decides to give them, instead of finding better
ways to create those maps. Sure. Let everyone use Slime and that f'ing
kludge Emacs. It will give you the signature--but it won't tell you
what it means. But that's all we have, so let's just keep using it.
Let's not progress any further. Everything's fine the way it is. I'm
fine with it, so everyone else should be, too. Only one programmer on
earth understands what Jack is doing, because I sure don't. When Jack
implements his new language and compiler, only Jack will ever
comprehend it. Jack must be the only one on earth with a brain. I wish
I was Jack.

Do you even see how distorted your thinking is?

>Ok, you keep saying that, and you keep using the #| |# reader syntax for
>comments, and somehow that is supposed to enlighten me. I implore you to
> boost the signal and reduce the noise in your posts.

Then take off the blindfold and remove the earplugs.

>How does allowing functions to share a name while differing in many
>other ways make comments unnecessary?

McFly! Allowing function to share the same name... has nothing to do
with making comments unnecessary. The code is the comment. The function
is the same: Open a zipfile and extract one or more files. Why should I
name everything differently when the connectives can convey the
difference.

>I was under the mistaken impression that you were
>interested in learning about common lisp and how to best use it.

What would make you think otherwise? Is your way the only best way to
use it?

>But remember
>that your ideas about what is concise and readable differ from others

Must remember. Must remember. Oh, wait! That's already pretty obvious
to me.

>(and from what i can see from your naming conventions, _most_ others),

(car foo)
(rest bar)
(first last)
(second third)

> so you can't just say that keywords are unreadable

I never said any such thing. I said they don't map well for connective
use.

> without backing it up in some way.

I've backed up my bull. You've come back with fallacies, twisted logic
and whining--I don't understand; I don't understand.

>when presenting an alternative to the way common lisp has
>solved a problem...

I didn't present anything for anyone's approval. I asked questions. A
couple of people helped my understanding. You questioned my reasons for
implementing something you don't understand.

>the burden of proof is on you.

Do I need to prove it to anyone? No. I'm just having fun watching you
avoid any kind of logic just to prove me wrong.

Or maybe you just want me to blather on about it, so that I can prove
to the rest of the world what a great language Lisp is for this type of
solution.

You want more? Bring it on!

--Jack

.


Quantcast