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

was: newline and concatenate. length of a lisp function

60 views
Skip to first unread message

Delaregue

unread,
Jul 25, 2001, 11:46:52 AM7/25/01
to
Sorry for the new post

I've found a way:
(concatenate 'string '(#\newline) "or (" c " =...etc...

My new born twins baby must be tiring me ;-)

Thomas F. Burdick

unread,
Jul 25, 2001, 3:14:59 PM7/25/01
to
dela...@netscape.net (Delaregue) writes:

While this will work, I find it horrid style to format strings this
way. Use FORMAT instead.

Frode Vatvedt Fjeld

unread,
Jul 25, 2001, 3:40:21 PM7/25/01
to
dela...@netscape.net (Delaregue) writes:

> I've found a way:
> (concatenate 'string '(#\newline) "or (" c " =...etc...

Although it tends to look a bit messy, you can have newline literals
in strings:

(concatenate 'string "
or (" c " = ..

--
Frode Vatvedt Fjeld

Kaz Kylheku

unread,
Jul 25, 2001, 3:58:55 PM7/25/01
to

Why not make a funtion called catenate, or cat, just for strings.
That eliminates the annoying 'string type parameter, and its name abuses
the language less (``catenate'' means to chain together, so the ``con''
prefix is superflous).

Invoking an interpretive formatter to glue strings together is neat,
but possibly inefficient, not to mention needlessly cryptic.

Christophe Rhodes

unread,
Jul 25, 2001, 4:25:40 PM7/25/01
to
k...@ashi.footprints.net (Kaz Kylheku) writes:

> >While this will work, I find it horrid style to format strings this
> >way. Use FORMAT instead.
>
> Why not make a funtion called catenate, or cat, just for strings.
> That eliminates the annoying 'string type parameter, and its name abuses
> the language less (``catenate'' means to chain together, so the ``con''
> prefix is superflous).

True, although current usage isn't quite as strict as you're
implying. The reason for not making a new function when an acceptable
idiom exists is that you raise the barrier for maintainability.



> Invoking an interpretive formatter to glue strings together is neat,
> but possibly inefficient, not to mention needlessly cryptic.

If it turns out that this format call is the speed-critical portion of
the application, you can always use formatter; personally, I'd find a
user function with a non-intuitive name[1] a lot more cryptic than
(format nil "~a~%~a" x y) or its formatter equivalent.

Cheers,

Christophe

[1] Ah, the irony... my idea for common-lisp-utilities was for
functionality that didn't have a convenient idiom already; so
partition and extremize, but not this catenate or Marco's make-array
wrapper. Since there doesn't seem to be much demand or even comment,
this is largely moot.
--
Jesus College, Cambridge, CB5 8BL +44 1223 510 299
http://www-jcsu.jesus.cam.ac.uk/~csr21/ (defun pling-dollar
(str schar arg) (first (last +))) (make-dispatch-macro-character #\! t)
(set-dispatch-macro-character #\! #\$ #'pling-dollar)

Kent M Pitman

unread,
Jul 25, 2001, 5:48:39 PM7/25/01
to
Christophe Rhodes <cs...@cam.ac.uk> writes:

> k...@ashi.footprints.net (Kaz Kylheku) writes:
>
> > >While this will work, I find it horrid style to format strings this
> > >way. Use FORMAT instead.
> >
> > Why not make a funtion called catenate, or cat, just for strings.
> > That eliminates the annoying 'string type parameter, and its name abuses
> > the language less (``catenate'' means to chain together, so the ``con''
> > prefix is superflous).
>
> True, although current usage isn't quite as strict as you're
> implying. The reason for not making a new function when an acceptable
> idiom exists is that you raise the barrier for maintainability.

Substantially. I personally would guess the aggregate cost to the
community of changing the name of the function from concatenate to
catentate would probably be in the multiple millions of dollars in
labor at the various companies where Lisp is installed and where a
change needs to be implemented. Had the industry such money to spend,
it would be better off spending it on R&D...

> > Invoking an interpretive formatter to glue strings together is neat,
> > but possibly inefficient, not to mention needlessly cryptic.
>
> If it turns out that this format call is the speed-critical portion of
> the application, you can always use formatter; personally, I'd find a
> user function with a non-intuitive name[1] a lot more cryptic than
> (format nil "~a~%~a" x y) or its formatter equivalent.

I think the most important stylistic thing to do when you have questions
like this is to abstract out the problem. Make a STRING-APPEND. There
are a million ways to implement one, but the really important thing is
to just get it to where the definition is in one place so that if you
decide to change it (e.g., to speed it up) the benefit will be felt in
all the points of use.

e.g.,

(defmacro defun-inline (name bvl &body forms)
`(progn (declaim (inline ,name))
(defun ,name ,bvl ,@forms)))

(defun-inline string-append (&rest strings)
(declare (dynamic-extent strings))
(apply #'concatenate 'string strings))

Btw, I do think FORMAT is likely to be slower than FORMAT. Among
other things, it goes through a stream interface which in a simple
case like this is serious overkill. Even IF you manage to stack-allocate
the stream and its associated buffers, which not all implementations will,
the time required to do that allocation is probably already as long as
some implementations would take to execute the CONCATENATE.

Erik Naggum

unread,
Jul 25, 2001, 6:17:51 PM7/25/01
to
* k...@ashi.footprints.net (Kaz Kylheku)

> Invoking an interpretive formatter to glue strings together is neat,
> but possibly inefficient, not to mention needlessly cryptic.

What made you believe it is "interpretive"? Have we not had this stupid
discussion about interpreter versus compiler enough times already?

As for cryptic, Greek is cryptic to non-Greeks. Just learn the language.
Ignorance of the language is no excuse.

#:Erik
--
There is nothing in this message that under normal circumstances should
cause Barry Margolin to announce his moral superiority over others, but
one never knows how he needs to behave to maintain his belief in it.

Kaz Kylheku

unread,
Jul 25, 2001, 6:36:16 PM7/25/01
to
In article <sfwr8v4...@world.std.com>, Kent M Pitman wrote:
>Christophe Rhodes <cs...@cam.ac.uk> writes:
>
>> k...@ashi.footprints.net (Kaz Kylheku) writes:
>>
>> > >While this will work, I find it horrid style to format strings this
>> > >way. Use FORMAT instead.
>> >
>> > Why not make a funtion called catenate, or cat, just for strings.
>> > That eliminates the annoying 'string type parameter, and its name abuses
>> > the language less (``catenate'' means to chain together, so the ``con''
>> > prefix is superflous).
>>
>> True, although current usage isn't quite as strict as you're
>> implying. The reason for not making a new function when an acceptable
>> idiom exists is that you raise the barrier for maintainability.
>
>Substantially. I personally would guess the aggregate cost to the
>community of changing the name of the function from concatenate to
>catentate would probably be in the multiple millions of dollars in

I never proposed a name change for the existing function; I for one
am happy that ``catenate'' is an available identifier so that you
can write your own function and call it that.

Kaz Kylheku

unread,
Jul 25, 2001, 6:53:56 PM7/25/01
to
In article <32050882...@naggum.net>, Erik Naggum wrote:
>* k...@ashi.footprints.net (Kaz Kylheku)
>> Invoking an interpretive formatter to glue strings together is neat,
>> but possibly inefficient, not to mention needlessly cryptic.
>
> What made you believe it is "interpretive"? Have we not had this stupid
> discussion about interpreter versus compiler enough times already?

What makes you believe that it's *never* interpretive? It's more likely
than not to be implemented that way---as a function which scans
the string and carries out the formatting actions described therein.

Since my comment was performance related, I had a likely common
implementation in mind, which could be possibly quite inefficient
for catenating strings.

Of course, I realize that (format nil "~A~A" x y) could be recognized
as an idiom, and translated into a direct catenation operation.

I also realize that the performance of the catenation of two strings
might not even matter.

Sorry if I upset anyone!

Kent M Pitman

unread,
Jul 25, 2001, 6:59:40 PM7/25/01
to
Erik Naggum <er...@naggum.net> writes:

> * k...@ashi.footprints.net (Kaz Kylheku)
> > Invoking an interpretive formatter to glue strings together is neat,
> > but possibly inefficient, not to mention needlessly cryptic.
>
> What made you believe it is "interpretive"? Have we not had this stupid
> discussion about interpreter versus compiler enough times already?
>
> As for cryptic, Greek is cryptic to non-Greeks. Just learn the language.
> Ignorance of the language is no excuse.

I'm sure a number of CL implementations don't compile format strings.
I think it's fair to characterize them as interpretive since they're
sort of like byte-code interpreters.

Tim Moore

unread,
Jul 25, 2001, 7:23:12 PM7/25/01
to
On Wed, 25 Jul 2001, Kaz Kylheku wrote:

> In article <32050882...@naggum.net>, Erik Naggum wrote:
> >* k...@ashi.footprints.net (Kaz Kylheku)
> >> Invoking an interpretive formatter to glue strings together is neat,
> >> but possibly inefficient, not to mention needlessly cryptic.
> >
> > What made you believe it is "interpretive"? Have we not had this stupid
> > discussion about interpreter versus compiler enough times already?
>
> What makes you believe that it's *never* interpretive? It's more likely
> than not to be implemented that way---as a function which scans
> the string and carries out the formatting actions described therein.

Since FORMATTER is in the language and public domain code exists for it,
I'd say it's quite likely that implementations do transform some calls to
FORMAT with constant format strings into calls of the (compiled) formatter
function. On the other hand, firing up the stream and format machinery
may be a bigger bottleneck than interpreting the format string. On the
third hand, do you really care?

Tim


Thomas F. Burdick

unread,
Jul 25, 2001, 7:26:52 PM7/25/01
to
Kent M Pitman <pit...@world.std.com> writes:

> Christophe Rhodes <cs...@cam.ac.uk> writes:
>
> > k...@ashi.footprints.net (Kaz Kylheku) writes:
> >
> > > Thomas F. Burdick <t...@OCF.berkeley.EDU> writes:
> > >
> > > >While this will work, I find it horrid style to format strings this
> > > >way. Use FORMAT instead.
> > >

[ ... ]


> > > Invoking an interpretive formatter to glue strings together is neat,
> > > but possibly inefficient, not to mention needlessly cryptic.
> >
> > If it turns out that this format call is the speed-critical portion of
> > the application, you can always use formatter; personally, I'd find a
> > user function with a non-intuitive name[1] a lot more cryptic than
> > (format nil "~a~%~a" x y) or its formatter equivalent.
>
> I think the most important stylistic thing to do when you have questions
> like this is to abstract out the problem. Make a STRING-APPEND. There
> are a million ways to implement one, but the really important thing is
> to just get it to where the definition is in one place so that if you
> decide to change it (e.g., to speed it up) the benefit will be felt in
> all the points of use.

[ ... ]
> Btw, I do think FORMAT is likely to be slower.
[assuming you meant to omit "than FORMAT"]


> Among other things, it goes through a stream interface which in a
> simple case like this is serious overkill. Even IF you manage to
> stack-allocate the stream and its associated buffers, which not all
> implementations will, the time required to do that allocation is
> probably already as long as some implementations would take to
> execute the CONCATENATE.

Hmm, my gut reaction is "so, what?". The problem is to stuff data
into fields of a formatted SQL query. Isn't that *exactly* the domain
of formatted i/o functions? I would find something like:
(format nil "select unique(~S.~S) from ~S, ~S~%where ~S.~S = ~S;"
table-one desired-field
table-one table-two
table-two join-field desired-join-value)
far preferable to:
(cat "select unique(" table-one "." desired-field ") "
"from " table-one ", " table-two #\newline
"where " table-two "." join-field " = " desired-join-value ";")

The only way I would ever use the second is if I had to for speed.
Maybe this is a style point where opinions can differ, but I find the
second version horrid and Perl-like, where the first keeps the SQL
together and comprehensible.

Kaz Kylheku

unread,
Jul 25, 2001, 7:37:33 PM7/25/01
to

Absolutely not! :)

cbbr...@hex.net

unread,
Jul 25, 2001, 8:43:18 PM7/25/01
to
Erik Naggum <er...@naggum.net> writes:
> * k...@ashi.footprints.net (Kaz Kylheku)
> > Invoking an interpretive formatter to glue strings together is neat,
> > but possibly inefficient, not to mention needlessly cryptic.

> What made you believe it is "interpretive"? Have we not had this
> stupid discussion about interpreter versus compiler enough times
> already?

Because C format strings describe an interpretive sublanguage, and few
ever think beyond that :-(.

More reasonably, it is not outrageous to anticipate that it's pretty
likely that

(format T "Some Directives ~A ~A ~A ~D~%" 'this 'that 'other 25)

may result in some runtime interpretation of the format string, whilst
(format T (formatter "Some Directives ~A ~A ~A ~D~%") 'this 'taht
'other 25)
is _guaranteed_ to involve some pre-compiling.
--
(concatenate 'string "cbbrowne" "@acm.org")
http://vip.hyperusa.com/~cbbrowne/linuxdistributions.html
"...In my phone conversation with Microsoft's lawyer I copped to the
fact that just maybe his client might see me as having been in the
past just a bit critical of their products and business
practices. This was too bad, he said with a sigh, because they were
having a very hard time finding a reporter who both knew the industry
well enough to be called an expert and who hadn't written a negative
article about Microsoft." -- Robert X. Cringely

cbbr...@hex.net

unread,
Jul 25, 2001, 8:56:32 PM7/25/01
to
t...@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> Kent M Pitman <pit...@world.std.com> writes:
> > Btw, I do think FORMAT is likely to be slower.
> [assuming you meant to omit "than FORMAT"]
> > Among other things, it goes through a stream interface which in a
> > simple case like this is serious overkill. Even IF you manage to
> > stack-allocate the stream and its associated buffers, which not all
> > implementations will, the time required to do that allocation is
> > probably already as long as some implementations would take to
> > execute the CONCATENATE.
>
> Hmm, my gut reaction is "so, what?".

Good point.

> The problem is to stuff data into fields of a formatted SQL query.
> Isn't that *exactly* the domain of formatted i/o functions? I would
> find something like:
> (format nil "select unique(~S.~S) from ~S, ~S~%where ~S.~S = ~S;"
> table-one desired-field
> table-one table-two
> table-two join-field desired-join-value)
> far preferable to:
> (cat "select unique(" table-one "." desired-field ") "
> "from " table-one ", " table-two #\newline
> "where " table-two "." join-field " = " desired-join-value ";")
>
> The only way I would ever use the second is if I had to for speed.
> Maybe this is a style point where opinions can differ, but I find
> the second version horrid and Perl-like, where the first keeps the
> SQL together and comprehensible.

You've not mentioned, but I'm sure it's the case, that "time doesn't
matter" in this case. The amount of time spent pushing the query out
to the DBMS and processing the results may be reasonably expected to
_vastly_ outweigh any time wasted on string catenation.

I'd suggest that this is a place where efficiency would be quite
nicely served by setting up a FORMATTER to save _most_ of the time
that gets lost by using a format scheme.

Thus:
(defparameter *unique-join-format*
(formatter "select unique(~S.~S) from ~S, ~S~ where ~S.~S = ~S;"))

along with:
(format nil *unique-join-format*

table-one desired-field
table-one table-two
table-two join-field desired-join-value)

It might even be a reasonable idea to have some scheme for "clause
formation" where the selection might get generated by a function call
looking vaguely like:

(gen-select :unique '((table-one desired-field))
:from '(table-one table-two)
:where '((= (table-two join-field) desired-join-value)))
--
(concatenate 'string "cbbrowne" "@ntlug.org")
http://vip.hyperusa.com/~cbbrowne/lisp.html
If you stand in the middle of a library and shout "Aaaaaaaaargh" at
the top of your voice, everyone just stares at you. If you do the same
thing on an aeroplane, why does everyone join in?

Erik Naggum

unread,
Jul 25, 2001, 8:10:47 PM7/25/01
to
* k...@ashi.footprints.net (Kaz Kylheku)

> What makes you believe that it's *never* interpretive?

I do not believe that. Why do you invent such stupid claims to ask me to
refute when nobody have said anything remotely like it?

> It's more likely than not to be implemented that way---as a function
> which scans the string and carries out the formatting actions described
> therein.

How do you wind up with that "more likely" conclusion? Geez. This is
how those arrogant ignorants who claim to know how to implement Lisp turn
out to be college drop-outs after a few overdoses of Scheme. Smart
people do that string traversal at compile-time and generate the most
efficient code that can be known at compile-time. This is not hard.
This is _not_ C's printf and like-minded idiocy.

Take a look at the formatter macro the next time you feel the urge to
tell people how they "most likely" implement format. A constant string
as format's second argument is a bloody obvious candidate for a compiler
macro to turn into a macro call to formatter.

> Since my comment was performance related, I had a likely common
> implementation in mind, which could be possibly quite inefficient for
> catenating strings.

How do you know that it is "likely common"? How much experience do you
have evaluating implementation techniques for such things? None, right?
You are just guessing and making up statistics about commonality as you
go. This is _dishonest_ of you. It would have been honest to admit you
made it up with no supporting evidence at all. This is _so_ annoying and
it happens all the time to people who have very little clue.

> Of course, I realize that (format nil "~A~A" x y) could be recognized as
> an idiom, and translated into a direct catenation operation.

Well, _that_ is fairly unlikely to be optimized away, as ~A does not only
print the characters of strings, but does a lot more work than that.
However, ~% and ~& do print only newlines. Please do not tell me that
'(#\Newline) is better than ~%.

> I also realize that the performance of the catenation of two strings
> might not even matter.

That is most probably true, but if it does not matter, the most
perspicuous solution should be chosen. In this case, that would actually
be writing to a string stream with several format calls, as the amount of
stuff to put into that "string" _will_ grow without bound over time.

> Sorry if I upset anyone!

I would have been much happier if you were sorry you had jumped to
conclusions from completely absent information, which would be the
_cause_ people would be upset. We have been over this "interpreter"
misconception _enough_ times already. Just grow a clue: If it would be
slow, somebody has already made it more efficient than you can think of.
People who just make random noise from their own lack of experience about
what other people with such experience would have done need to be refuted
and corrected -- over and over again, because the very idea that somebody
might have more experience and _might_ have solved their obvious problem
simply does not occur to these people, unfathomable as that really is.

There are so many completely bogus reasons _not_ to use good solutions in
Common Lisp that never apply to any other language. Why is this? Is it
fear of having to know more about Common Lisp than other languages? Look
at what people do in Perl, Java, og C++, for crying out loud! And format
is supposed to be slow and cryptic? Gimme a _break_! When talking to an
SQL database! Sheesh.

Ignorance of the language is no excuse. Sorry for repeating myself.

Peter Van Eynde

unread,
Jul 26, 2001, 8:20:17 AM7/26/01
to
cbbr...@hex.net writes:

>> Isn't that *exactly* the domain of formatted i/o functions? I would
>> find something like:
>> (format nil "select unique(~S.~S) from ~S, ~S~%where ~S.~S = ~S;"
>> table-one desired-field
>> table-one table-two
>> table-two join-field desired-join-value)
>> far preferable to:
>> (cat "select unique(" table-one "." desired-field ") "
>> "from " table-one ", " table-two #\newline
>> "where " table-two "." join-field " = " desired-join-value ";")
>>
>> The only way I would ever use the second is if I had to for speed.
>> Maybe this is a style point where opinions can differ, but I find
>> the second version horrid and Perl-like, where the first keeps the
>> SQL together and comprehensible.
>
> You've not mentioned, but I'm sure it's the case, that "time doesn't
> matter" in this case. The amount of time spent pushing the query out
> to the DBMS and processing the results may be reasonably expected to
> _vastly_ outweigh any time wasted on string catenation.

I'll probably be late with this, but I've had some bad experience with
this kind of stuff, so:

SQL needs quoting for some characters etc. You are not doing so in the
examples given, this in the end will end up hurting you. Most SQL
interfaces have a seperate, less primitive interface where you do
thinks like:

(prepare-query "select unique(?,?) from ?, ? where ? = ?")
(setf (query-parameter 1) 'foo
(query-parameter 2) 'bar
(query-parameter 3) 'table-a
(query-parameter 4) 'table-b
(query-parameter 5) 'foo
(query-parameter 6) 45)
(execute-query)

This gives you
- higher speed, as you can just update the parameters in a loop.
- type safety, as the SQL interface can check what you've given it
- automatic quoting beyond what is posssible in the simple queries
(for example for BLOB's)

And in fact it is even simpler to use. On second thought: why don't
you use MaiSQL? :-)

Groetjes, Peter

--
It's logic Jim, but not as we know it. | pvan...@debian.org
"God, root, what is difference?" - Pitr|
"God is more forgiving." - Dave Aronson| http://cvs2.cons.org/~pvaneynd/

cbbr...@hex.net

unread,
Jul 26, 2001, 4:44:28 PM7/26/01
to
Peter Van Eynde <pvan...@debian.org> writes:
> cbbr...@hex.net writes:
>
> >> Isn't that *exactly* the domain of formatted i/o functions? I would
> >> find something like:
> >> (format nil "select unique(~S.~S) from ~S, ~S~%where ~S.~S = ~S;"
> >> table-one desired-field
> >> table-one table-two
> >> table-two join-field desired-join-value)
> >> far preferable to:
> >> (cat "select unique(" table-one "." desired-field ") "
> >> "from " table-one ", " table-two #\newline
> >> "where " table-two "." join-field " = " desired-join-value ";")
> >>
> >> The only way I would ever use the second is if I had to for speed.
> >> Maybe this is a style point where opinions can differ, but I find
> >> the second version horrid and Perl-like, where the first keeps the
> >> SQL together and comprehensible.
> >
> > You've not mentioned, but I'm sure it's the case, that "time doesn't
> > matter" in this case. The amount of time spent pushing the query out
> > to the DBMS and processing the results may be reasonably expected to
> > _vastly_ outweigh any time wasted on string catenation.

> I'll probably be late with this, but I've had some bad experience
> with this kind of stuff, so:

> SQL needs quoting for some characters etc. You are not doing so in
> the examples given, this in the end will end up hurting you.

True enough; I'd noticed, but not commented on that. For instance, a
query might look like:

select * from some-table where name='Christopher Browne';

That needs a bit of quoting and such, and this is _NOT_ in the form
typically used for quoting.

> Most SQL interfaces have a seperate, less primitive interface where
> you do thinks like:

> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
> (setf (query-parameter 1) 'foo
> (query-parameter 2) 'bar
> (query-parameter 3) 'table-a
> (query-parameter 4) 'table-b
> (query-parameter 5) 'foo
> (query-parameter 6) 45)
> (execute-query)

> This gives you
> - higher speed, as you can just update the parameters in a loop.
> - type safety, as the SQL interface can check what you've given it
> - automatic quoting beyond what is posssible in the simple queries
> (for example for BLOB's)

Yes, that looks pretty sensible...

> And in fact it is even simpler to use. On second thought: why don't
> you use MaiSQL? :-)

--
(reverse (concatenate 'string "ac.notelrac.teneerf@" "454aa"))
http://vip.hex.net/~cbbrowne/sap.html
Objects & Markets
"Object-oriented programming is about the modular separation of what
from how. Market-oriented, or agoric, programming additionally allows
the modular separation of why."
-- Mark Miller

Arseny Slobodjuck

unread,
Jul 27, 2001, 6:23:55 AM7/27/01
to
On 25 Jul 2001 08:46:52 -0700, dela...@netscape.net (Delaregue)
wrote:

>I've found a way:
> (concatenate 'string '(#\newline) "or (" c " =...etc...

Then look at this (I've recently learned a backquote):

;------ delim-out . solves problem with comma
;------ may be even shorter
(defun delim-out(list stream separators)
(princ (first separators) stream)
(loop for x on list do
(if (listp (car x))
(delim-out (cdr (car x)) stream
(cond ((eq (caar x) '&&) '("((" ") AND (" "))"))
((eq (caar x) '||) '("((" ") OR (" "))"))
((eq (caar x) '[) '("(" " " ")"))
((eq (caar x) '++) '(" " ", " ""))
(t (progn (princ (caar x) stream) '(" " " " "")))))
(if (eq (car x) '++)
(princ "," stream)
(princ (car x) stream)))
(when (cdr x) (princ (second separators) stream)))
(princ (third separators) stream))


(defun sql-out(list)
(with-output-to-string (string-stream)
(delim-out list string-stream '("" " " ""))))

(defparameter a 17)
(defparameter b 74)
(defparameter match 'qwerty)

(print
(sql-out `(select (++ A B C) from list where
(&& (field in ([ select id from ids))
(|| (,match = ,a) (,match = ,b))) )))

;or, more directly:

(print
(sql-out `(select A ++ B ++ C from list where
field in ([ select id from ids)
and ([ ,match = ,a or ,match = ,b))))

Mike McDonald

unread,
Jul 27, 2001, 11:48:35 PM7/27/01
to
In article <Mi%77.26492$PA1.2...@news20.bellglobal.com>,

cbbr...@hex.net writes:
> Peter Van Eynde <pvan...@debian.org> writes:

>> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
>> (setf (query-parameter 1) 'foo
>> (query-parameter 2) 'bar
>> (query-parameter 3) 'table-a
>> (query-parameter 4) 'table-b
>> (query-parameter 5) 'foo
>> (query-parameter 6) 45)
>> (execute-query)
>
>> This gives you
>> - higher speed, as you can just update the parameters in a loop.
>> - type safety, as the SQL interface can check what you've given it
>> - automatic quoting beyond what is posssible in the simple queries
>> (for example for BLOB's)
>
> Yes, that looks pretty sensible...

Sensible? Using numeric parameter numbers looks pretty horrible to me. Ever
time someone modifies the query, all hell will break out.

Mike McDonald
mik...@mikemac.com

Greg Menke

unread,
Jul 28, 2001, 12:50:46 AM7/28/01
to

>
> >> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
> >> (setf (query-parameter 1) 'foo
> >> (query-parameter 2) 'bar
> >> (query-parameter 3) 'table-a
> >> (query-parameter 4) 'table-b
> >> (query-parameter 5) 'foo
> >> (query-parameter 6) 45)
> >> (execute-query)
> >
> >> This gives you
> >> - higher speed, as you can just update the parameters in a loop.
> >> - type safety, as the SQL interface can check what you've given it
> >> - automatic quoting beyond what is posssible in the simple queries
> >> (for example for BLOB's)
> >
> > Yes, that looks pretty sensible...
>
> Sensible? Using numeric parameter numbers looks pretty horrible to me. Ever
> time someone modifies the query, all hell will break out.

Its a little horrible, but I don't think its all that fragile- a name
based approach would be very desirable.. The example above formats a
sql statement, presumably substituting the '?' marks with either a
constant or the value a symbol. Once execute-query returns, "output"
symbols, somehow indicated, would contain the query output values.

I think its in the right direction for managing complex sets of output
rows, where the rows can be iterated over, modified and committed back
to the source table. Its one thing Visual Basic does somewhat well &
its quite useful.

On the other hand, the technique tends to hold database cursors open
along with whatever locks the back end enforces, making concurrency a
bit harder to manage. Its not a problem with trivial statements where
the involvement of many tables and layers of queries is minimal, but
when things get complicated its harder to manage.

I think a slightly better approach would provide two alternatives,
first; a preformatted query might generate a list of object instances
or sublists, one per output row with the query closed immediately
after the fetch. The user can then fiddle with the data and just let
it go as convienent and no database resources are locked. This could
work for bulk updates too. Normal mapping semantics would probably be
a good match with it. Lots of the client/server database API's have a
basic interface like this & I think it would fit well with Lisp.

The 2nd approach would be a result-set approach, presumably slower,
but allowing the client software to navigate the set and update it in
a piecemeal fashion.

Both approaches could be performed in a transaction.

http://ww.telent.net/cliki/Pg

is a good beginning, providing SQL access at pretty much the right
level.

Greg Menke

cbbr...@hex.net

unread,
Jul 28, 2001, 1:40:57 AM7/28/01
to

I don't mind making "favorable gruntings" about something that's at
least moving towards being better. It may not be the final answer, but
it's a step towards "rightness," unlike:

(let ((query (concatenate 'string
"select unique(" foo "," bar ") from " baz " where "
foo " = '" "45" "';")))
(process-query query))

Not entirely incidentally, one of JDBC's query mechanisms is very much
similar to the "query-parameter" approach.

Furthermore, I'd have _no_ problem with the notion of having something
perhaps as ugly as QUERY-PARAMETER doing the work underneath, with a
wrapper that Makes it Pretty on top...


--
(concatenate 'string "cbbrowne" "@acm.org")

http://www.ntlug.org/~cbbrowne/spreadsheets.html
Rules of the Evil Overlord #160. "Before being accepted into my
Legions of Terror, potential recruits will have to pass peripheral
vision and hearing tests, and be able to recognize the sound of a
pebble thrown to distract them." <http://www.eviloverlord.com/>

Peter Van Eynde

unread,
Jul 29, 2001, 3:56:18 PM7/29/01
to
mik...@mikemac.com (Mike McDonald) writes:

>>> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
>>> (setf (query-parameter 1) 'foo
>>> (query-parameter 2) 'bar
>>> (query-parameter 3) 'table-a
>>> (query-parameter 4) 'table-b
>>> (query-parameter 5) 'foo
>>> (query-parameter 6) 45)
>>> (execute-query)

> Sensible? Using numeric parameter numbers looks pretty horrible to me. Ever


> time someone modifies the query, all hell will break out.

It is. A more advanced library would use symbolic names. But most
available interfaces (ODBC and JDBC it seems) only give you numeric
indexes. Extending the prepare-query and setf-er to accept ?foo
variables is pretty easy I guess. But I didn't think of it :-)

I just wanted to point out that concatenating a query string together
is the road to hell.

Peter Van Eynde

unread,
Jul 29, 2001, 4:03:16 PM7/29/01
to
Greg Menke <gregm...@mindspring.com> writes:

> On the other hand, the technique tends to hold database cursors open
> along with whatever locks the back end enforces, making concurrency a
> bit harder to manage. Its not a problem with trivial statements where
> the involvement of many tables and layers of queries is minimal, but
> when things get complicated its harder to manage.

Just a comment (but we are straying a bit far from c.l.l): I've
noticed that most interfaces have limited or non-implemented
roll-back/commit functionality. So it you want to do something more
complex, IMHO it is better to use the DB's own 'language' (I cannot
bring myself to call the only horror I sort-of-know: CY/FDY a
language) to implement complex operation. Then just use the interface
to call those procedures. If you manage to write those procedures
automagicly from Lisp, you're made the world a better place :-)

<realism>At least this way you can send the DB-vendor bugreports using
only their products, so they cannot point the finger at Lisp
anymore</realism>

Greg Menke

unread,
Jul 29, 2001, 7:16:16 PM7/29/01
to

> >>> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
> >>> (setf (query-parameter 1) 'foo
> >>> (query-parameter 2) 'bar
> >>> (query-parameter 3) 'table-a
> >>> (query-parameter 4) 'table-b
> >>> (query-parameter 5) 'foo
> >>> (query-parameter 6) 45)
> >>> (execute-query)
>
> > Sensible? Using numeric parameter numbers looks pretty horrible to me. Ever
> > time someone modifies the query, all hell will break out.
>
> It is. A more advanced library would use symbolic names. But most
> available interfaces (ODBC and JDBC it seems) only give you numeric
> indexes. Extending the prepare-query and setf-er to accept ?foo
> variables is pretty easy I guess. But I didn't think of it :-)
>
> I just wanted to point out that concatenating a query string together
> is the road to hell.
>

I suspect database access is pretty much coincident with the road to
hell to begin with. The opposite end of the spectrum might be the
Visual Basic "data object" regime where an object represents a
table/query and a set of "field" objects are linked to it, which
produce values for queries or accept them for update, essentially
dispersing the structure of the query or update across a variety of
objects. The string concat approach at least consolidates the query-
which can be quite helpful.

Though I've not tried it yet, I think something like plob could be a
better idea; it seems as if it is lots easier to fetch/update data
with it. At least it looks possible to avoid the tedious & fragile
query setup & execution of the traditional SQL database api's.

Gregm

cbbr...@hex.net

unread,
Jul 29, 2001, 8:23:58 PM7/29/01
to

I'm fairly impressed with the "use a format string" approach; as a
first-approximation to OK-ness, it's not half bad.

> Though I've not tried it yet, I think something like plob could be a
> better idea; it seems as if it is lots easier to fetch/update data
> with it. At least it looks possible to avoid the tedious & fragile
> query setup & execution of the traditional SQL database api's.

The problem I see with the "object" databases is that while they may
nicely tie to having "active data," they lose the SQL/relational merit
of representing a more-or-less algebraic description that you can
"reason" about.

That is, in a "persistent object" system, the data can get hidden
inside the code, whereas SQL systems have [along with various
demerits] the merit that there's a data "dictionary" to look at to
figure out what tables are there in which to find useful information.

If those tables are basically representing mazes of pointers, then I
guess there's no benefit, but if applications are built with a "table"
orientation, the static description definitely provides benefit...
--
(reverse (concatenate 'string "gro.gultn@" "enworbbc"))
http://vip.hyperusa.com/~cbbrowne/rdbms.html
"What a depressingly stupid machine."
-- Marvin the Paranoid Android

Tim Bradshaw

unread,
Jul 29, 2001, 9:38:30 PM7/29/01
to
* cbbrowne wrote:
> The problem I see with the "object" databases is that while they may
> nicely tie to having "active data," they lose the SQL/relational merit
> of representing a more-or-less algebraic description that you can
> "reason" about.

This argument is number 3 on Bradshaw's list of great Computer Science
cretinisms:

`We have this problem which is difficult. We have a formalism
which is not particularly useful for dealing with the problem, but
has a lot of nice properties that we understand. So we'll use
this formalism. It won't help us solve the problem but it's got
these good properties, see...'

The static-type people are the canonical example of this cretinism:

`statically typed languages have wonderful properties, you never
get run-time type errors, you can prove correctness in certain
carefully-chosen small examples, you can publish lots of papers on
type theory. OK they don't help solve any interesting problems,
and the carefully-chosen small examples bear no relation to real
programs, but who cares about that?'.

One of Lisp's many virtues is its total disdaim for this cretinism.

--tim

F. Xavier Noria

unread,
Jul 29, 2001, 11:02:39 PM7/29/01
to
On 30 Jul 2001 02:38:30 +0100, Tim Bradshaw <t...@cley.com> wrote:

: * cbbrowne wrote:
:> The problem I see with the "object" databases is that while they may
:> nicely tie to having "active data," they lose the SQL/relational merit
:> of representing a more-or-less algebraic description that you can
:> "reason" about.
:
: This argument is number 3 on Bradshaw's list of great Computer Science
: cretinisms:

Sounds promising! I haven't been able to find that list with Google,
is published somewhere on the net?

-- fxn

Tim Bradshaw

unread,
Jul 31, 2001, 9:14:51 AM7/31/01
to

It is obtainable by sending three pints of your blood to Bradshaw
Industries PLC. Don't try sending anyone else's blood: we'll know
it's not yours.


Barry Margolin

unread,
Jul 31, 2001, 2:38:49 PM7/31/01
to
In article <86lml7w...@debian.org>,

Peter Van Eynde <pvan...@debian.org> wrote:
>mik...@mikemac.com (Mike McDonald) writes:
>
>>>> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
>>>> (setf (query-parameter 1) 'foo
>>>> (query-parameter 2) 'bar
>>>> (query-parameter 3) 'table-a
>>>> (query-parameter 4) 'table-b
>>>> (query-parameter 5) 'foo
>>>> (query-parameter 6) 45)
>>>> (execute-query)
>
>> Sensible? Using numeric parameter numbers looks pretty horrible to me. Ever
>> time someone modifies the query, all hell will break out.
>
>It is. A more advanced library would use symbolic names. But most
>available interfaces (ODBC and JDBC it seems) only give you numeric
>indexes. Extending the prepare-query and setf-er to accept ?foo
>variables is pretty easy I guess. But I didn't think of it :-)

A likely reason for the above style is that it's easily implemented across
a wide variety of programming languages. The embedded SQL statements can
be taken from a C, COBOL, or Perl program and dropped verbatim in the Lisp
program.

In Perl's DBI module, numeric parameters aren't typically used. Instead, a
query object has an execute method that takes the parameters as positional
arguments, something like:

$query->execute("foo", "bar", ...);

I expect that some of the Lisp DB interfaces have something similar. But
positional parameters to a function are only slightly easier to maintain
than numeric parameters; the main benefit is that you can't screw up by
accidentally mistyping a parameter number, but if you insert a new
parameter you still have to find all the users of the prepared query and
update their parameter lists by counting delimiters.

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, 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.

Barry Margolin

unread,
Jul 31, 2001, 2:49:50 PM7/31/01
to
In article <32050950...@naggum.net>, Erik Naggum <er...@naggum.net> wrote:
>* k...@ashi.footprints.net (Kaz Kylheku)
> How do you know that it is "likely common"? How much experience do you
> have evaluating implementation techniques for such things? None, right?
> You are just guessing and making up statistics about commonality as you
> go. This is _dishonest_ of you. It would have been honest to admit you
> made it up with no supporting evidence at all. This is _so_ annoying and
> it happens all the time to people who have very little clue.

I don't know what actual implementors have done, but IMHO optimizing FORMAT
seems like it would be a pretty low priority, compared to most of the other
optimizations a vendor might consider doing. FORMAT is often used in
conjunction with output to devices that are relatively slow compared to the
processor (e.g. networks, disks, terminals). In such cases, the speed of
FORMAT is usually irrelevant, because the bottleneck is in the output
routine, not the data formatting.

But that's just my opinion, I could be wrong (as Dennis Miller says).
People asked for the FORMATTER function, and one can certainly hope that
implementors did something useful with this better than:

(defun formatter (format-string)
#'(lambda (stream &rest args)
(apply #'format stream format-string args)))

(If I didn't get the interface correct, I apologize, as my computer is in a
state that makes it difficult for me to access the CLHS to check.)

Reini Urban

unread,
Aug 9, 2001, 3:53:42 AM8/9/01
to
Peter Van Eynde <pvan...@debian.org> wrote:
: mik...@mikemac.com (Mike McDonald) writes:
:>>> (prepare-query "select unique(?,?) from ?, ? where ? = ?")
:>>> (setf (query-parameter 1) 'foo
:>>> (query-parameter 2) 'bar
:>>> (query-parameter 3) 'table-a
:>>> (query-parameter 4) 'table-b
:>>> (query-parameter 5) 'foo
:>>> (query-parameter 6) 45)
:>>> (execute-query)

: I just wanted to point out that concatenating a query string together


: is the road to hell.

I prefer hell over numeric indices or symbolic names.
(as in the winston-horn matcher: where ?name=?qname)

simplicity first, god mode later.
--
Reini Urban
http://xarch.tu-graz.ac.at/acadwiki/AutoLispFaq

glauber

unread,
Aug 9, 2001, 3:58:23 PM8/9/01
to
Barry Margolin <bar...@genuity.net> wrote in message news:<i5D97.20$TO3.232@burlma1-snr2>...
[..]

> People asked for the FORMATTER function, and one can certainly hope that
> implementors did something useful with this better than:
>
> (defun formatter (format-string)
> #'(lambda (stream &rest args)
> (apply #'format stream format-string args)))
[...]

In CLisp, for example,
(formatter "~12:d ~a~%")
returns
#<CLOSURE :LAMBDA (STREAM #:ARG1091 #:ARG1092 &REST #:ARGS1088)
(DECLARE (IGNORABLE STREAM))
(DECLARE (IGNORABLE #:ARG1091 #:ARG1092 #:ARGS1088))
(SYSTEM::DO-FORMAT-DECIMAL STREAM T NIL 12 NIL NIL NIL #:ARG1091)
(WRITE-CHAR #\Space STREAM) (PRINC #:ARG1092 STREAM) (TERPRI STREAM)
#:ARGS1088>


So it looks like it converts the format string to the helper functions
that are actually called by format. One would hope (but i have no time
to confirm now) that it uses the exact same mechanism that format
does. The only advantage i can think of is that the stuff returned by
formatter can be compiled.


g

0 new messages