From: Delaregue
Subject: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <6b4aa54a.0107250746.7782514e@posting.google.com>
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 ;-)

From: Thomas F. Burdick
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <xcv7kwwstvw.fsf@conquest.OCF.Berkeley.EDU>
·········@netscape.net (Delaregue) writes:

> 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 ;-)

While this will work, I find it horrid style to format strings this
way.  Use FORMAT instead.
From: Kaz Kylheku
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <3yF77.3090$BN6.79113@news1.rdc1.bc.home.com>
In article <···············@conquest.OCF.Berkeley.EDU>, Thomas F. Burdick wrote:
>·········@netscape.net (Delaregue) writes:
>
>> 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 ;-)
>
>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).

Invoking an interpretive formatter to glue strings together is neat,
but possibly inefficient, not to mention needlessly cryptic.
From: Christophe Rhodes
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <sq7kwwiwmz.fsf@lambda.jesus.cam.ac.uk>
···@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)
From: Kent M Pitman
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <sfwr8v4he88.fsf@world.std.com>
Christophe Rhodes <·····@cam.ac.uk> writes:

> ···@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.
From: Thomas F. Burdick
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <xcvzo9sr3nn.fsf@conquest.OCF.Berkeley.EDU>
Kent M Pitman <······@world.std.com> writes:

> Christophe Rhodes <·····@cam.ac.uk> writes:
> 
> > ···@ashi.footprints.net (Kaz Kylheku) writes:
> > 
> > > Thomas F. Burdick <···@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.
From: ········@hex.net
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <4VJ77.25581$eY6.2790428@news20.bellglobal.com>
···@conquest.OCF.Berkeley.EDU (Thomas F. Burdick) writes:
> Kent M Pitman <······@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?
From: Peter Van Eynde
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <86k80vvq4e.fsf@debian.org>
········@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. | ········@debian.org
"God, root, what is difference?" - Pitr|
"God is more forgiving." - Dave Aronson| http://cvs2.cons.org/~pvaneynd/
From: ········@hex.net
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <Mi%77.26492$PA1.2842848@news20.bellglobal.com>
Peter Van Eynde <········@debian.org> writes:
> ········@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 ····················@" "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
From: Mike McDonald
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <nCq87.854$4H4.1453840@e3500-chi1.usenetserver.com>
In article <·······················@news20.bellglobal.com>,
	········@hex.net writes:
> Peter Van Eynde <········@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
  ·······@mikemac.com
From: Greg Menke
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <m3snfh64ih.fsf@europa.mindspring.com>
> 
> >> (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
From: Peter Van Eynde
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <86hevvwliz.fsf@debian.org>
Greg Menke <··········@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>

Groetjes, Peter

-- 
It's logic Jim, but not as we know it. | ········@debian.org
"God, root, what is difference?" - Pitr|
"God is more forgiving." - Dave Aronson| http://cvs2.cons.org/~pvaneynd/
From: ········@hex.net
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <Jfs87.44010$eY6.4673974@news20.bellglobal.com>
·······@mikemac.com (Mike McDonald) writes:
> In article <·······················@news20.bellglobal.com>,
> 	········@hex.net writes:
> > Peter Van Eynde <········@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.

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/>
From: Peter Van Eynde
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <86lml7wlul.fsf@debian.org>
·······@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.

Groetjes, Peter

-- 
It's logic Jim, but not as we know it. | ········@debian.org
"God, root, what is difference?" - Pitr|
"God is more forgiving." - Dave Aronson| http://cvs2.cons.org/~pvaneynd/
From: Greg Menke
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <m3ae1nz5q7.fsf@europa.mindspring.com>
> >>> (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
From: ········@hex.net
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <yO197.4966$Q13.488659@news20.bellglobal.com>
Greg Menke <··········@mindspring.com> 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.

> 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.

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 ··········@" "enworbbc"))
http://vip.hyperusa.com/~cbbrowne/rdbms.html
"What a depressingly stupid machine."
-- Marvin the Paranoid Android
From: Tim Bradshaw
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <ey38zh7w609.fsf@cley.com>
* 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
From: F. Xavier Noria
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <9k2iof$544f26@news1s.iddeo2.es>
On 30 Jul 2001 02:38:30 +0100, Tim Bradshaw <···@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
From: Tim Bradshaw
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <ey3hevttf3o.fsf@cley.com>
* F Xavier Noria wrote:
> On 30 Jul 2001 02:38:30 +0100, Tim Bradshaw <···@cley.com> wrote:
> : 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?

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.
From: Barry Margolin
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <YWC97.19$TO3.155@burlma1-snr2>
In article <··············@debian.org>,
Peter Van Eynde  <········@debian.org> wrote:
>·······@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, ······@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.
From: Reini Urban
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <9ktfi6$jr$2@fstgss02.tu-graz.ac.at>
Peter Van Eynde <········@debian.org> wrote:
: ·······@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
From: Kaz Kylheku
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <ARH77.3364$BN6.104649@news1.rdc1.bc.home.com>
In article <···············@world.std.com>, Kent M Pitman wrote:
>Christophe Rhodes <·····@cam.ac.uk> writes:
>
>> ···@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.
From: Erik Naggum
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <3205088270665958@naggum.net>
* ···@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.
From: Kaz Kylheku
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <86I77.3414$BN6.107675@news1.rdc1.bc.home.com>
In article <················@naggum.net>, Erik Naggum wrote:
>* ···@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!
From: Tim Moore
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <9jnkd0$43m$0@216.39.145.192>
On Wed, 25 Jul 2001, Kaz Kylheku wrote:

> In article <················@naggum.net>, Erik Naggum wrote:
> >* ···@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
From: Kaz Kylheku
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <1LI77.3482$BN6.115864@news1.rdc1.bc.home.com>
In article <············@216.39.145.192>, Tim Moore wrote:
>On Wed, 25 Jul 2001, Kaz Kylheku wrote:
>> 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?

Absolutely not! :)
From: Erik Naggum
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <3205095043611228@naggum.net>
* ···@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.

#: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.
From: Barry Margolin
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <i5D97.20$TO3.232@burlma1-snr2>
In article <················@naggum.net>, Erik Naggum  <····@naggum.net> wrote:
>* ···@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.)

-- 
Barry Margolin, ······@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.
From: glauber
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <892f97d1.0108091158.447af3dc@posting.google.com>
Barry Margolin <······@genuity.net> wrote in message news:<················@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
From: Kent M Pitman
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <sfwsnfk399f.fsf@world.std.com>
Erik Naggum <····@naggum.net> writes:

> * ···@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.
From: ········@hex.net
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <GIJ77.25444$eY6.2779925@news20.bellglobal.com>
Erik Naggum <····@naggum.net> writes:
> * ···@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
From: Frode Vatvedt Fjeld
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <2hk80wu7a2.fsf@dslab7.cs.uit.no>
·········@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
From: Arseny Slobodjuck
Subject: Re: was: newline and concatenate. length of a lisp function
Date: 
Message-ID: <3b614076.2918156@news.vtc.ru>
On 25 Jul 2001 08:46:52 -0700, ·········@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))))