····@stablecross.com (Bob Felts) writes:
> Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
Because symbols are "string designators" which can be used in place of
strings. And nil is a symbol with the symbol-name "NIL", which is
therefore used as the string being processed by STRING-TRIM.
Compare:
(string-trim '(#\Tab) "NIL")
(string-trim '(#\Tab) 'foo)
(string-trim '(#\Tab) t)
--
Thomas A. Russ, USC/Information Sciences Institute
On 2008-04-02 21:14:37 -0400, ····@stablecross.com (Bob Felts) said:
> Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
Because string-trim returns a string not a string designator. "NIL" is
a string and nil, though a string designator and therfore suitable as
the second arg, is not a string and so cannot be the return value.
"Function STRING-TRIM, STRING-LEFT-TRIM, STRING-RIGHT-TRIM
Syntax:
string-trim character-bag string => trimmed-string
string-left-trim character-bag string => trimmed-string
string-right-trim character-bag string => trimmed-string
Arguments and Values:
character-bag---a sequence containing characters.
string---a string designator.
trimmed-string---a string."
P� Thu, 03 Apr 2008 03:14:37 +0200, skrev Bob Felts <····@stablecross.com>:
> Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
As a curiosity string-lessp treats nil as "NIL" as well.
(At least under LispWorks.)
--------------
John Thingstad
And very nice, too that truth is better than falsity. Or at least
better than nothing:
(string-greaterp t nil) => T
--
Thomas A. Russ, USC/Information Sciences Institute
P� Thu, 03 Apr 2008 03:14:37 +0200, skrev Bob Felts <····@stablecross.com>:
> Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
Perhaps Kent Pitman can enlighten us on the rather obnoxious practice of
treating nil as "NIL"?
--------------
John Thingstad
> Perhaps Kent Pitman can enlighten us on the rather obnoxious practice
> of treating nil as "NIL"?
I'm certainly not as knowledgable as Kent Pitman, but I would still
have expected that behaviour.
The name makes it clear that the function operates on strings, not
sequences, so what do you think it should do when given a symbol?
Shouldn't it treat it as a string designator?
Now, if FNORD designates "FNORD" (what else should it designate?), why
shouldn't NIL designate "NIL"? I'd find treating NIL as anything
different (like the empty string or whatever) very confusing in light
of this.
~ Matthias
On Thu, 03 Apr 2008 13:16:15 -0700, Matthias Benkard wrote:
>> Perhaps Kent Pitman can enlighten us on the rather obnoxious practice
>> of treating nil as "NIL"?
>
> I'm certainly not as knowledgable as Kent Pitman, but I would still
> have expected that behaviour.
>
> The name makes it clear that the function operates on strings, not
> sequences, so what do you think it should do when given a symbol?
> Shouldn't it treat it as a string designator? ...
> ~ Matthias
See
http://www.lisp.org/HyperSpec/Issues/iss329-writeup.html
"CLtL is inconsistent about the argument coercion performed by
the referenced functions. Page 299 says that the <string> argument can be
either a symbol or a string. Page 304 says that these functions effectively
call the STRING function, thus accepting a symbol, a string, or a character.
Neither page lists the set of affected functions explicitly. Page 304 says
that if any other data type is used, an error is signalled. But some
implementations allow other types, such as pathnames, to be coerced to
strings, which page 299 appears to allow but page 304 appears to forbid. In
some implementations these coercions are under user control via methods for
a generic function."
At issue is "Which functions convert symbols to strings?". I don't think
this issue was ever really completely clarified.
You just need to be aware that if you pass a symbol to a string function
it might convert the symbol to a string before using it.
Tim
On 3 Apr., 22:32, tim <····@internet.com> wrote:
> At issue is "Which functions convert symbols to strings?". I don't think
> this issue was ever really completely clarified.
>
> You just need to be aware that if you pass a symbol to a string function
> it might convert the symbol to a string before using it.
From CLHS 16.2:
"Syntax:
string-trim character-bag string => trimmed-string
...
string---a string designator."
From the glossary:
"string designator n. a designator for a string; that is, an object
that denotes a string and that is one of: a character (denoting a
singleton string that has the character as its only element), a symbol
(denoting the string that is its name), or a string (denoting itself).
The intent is that this term be consistent with the behavior of
string; implementations that extend string must extend the meaning of
this term in a compatible way."
I've always considered this to be quite unambiguous... Is there still
an ambiguity somewhere in the standard?
~ Matthias
tim <····@internet.com> writes:
> On Thu, 03 Apr 2008 13:16:15 -0700, Matthias Benkard wrote:
>
>>> Perhaps Kent Pitman can enlighten us on the rather obnoxious
>>> practice of treating nil as "NIL"?
>>
>> I'm certainly not as knowledgable as Kent Pitman, but I would still
>> have expected that behaviour.
>>
>> The name makes it clear that the function operates on strings, not
>> sequences, so what do you think it should do when given a symbol?
>> Shouldn't it treat it as a string designator? ... ~ Matthias
>
> See
>
> http://www.lisp.org/HyperSpec/Issues/iss329-writeup.html
>
>
> At issue is "Which functions convert symbols to strings?". I don't think
> this issue was ever really completely clarified.
It was clarified by the introduction of the notion of "string
designator":
string designator n.
a designator for a string; that is, an object that denotes a string
and that is one of: a character (denoting a singleton string that
has the character as its only element), a symbol (denoting the
string that is its name), or a string (denoting itself). The
intent is that this term be consistent with the behavior of
‘string’; implementations that extend ‘string’ must extend the
meaning of this term in a compatible way.
Note that all the functions mentioned in that writeup take string
designators, and therefore implicitly operate on whatever STRING
returns for the appropriate argument.
> You just need to be aware that if you pass a symbol to a string function
> it might convert the symbol to a string before using it.
In fact the string functions are /required/ to act on the string
returned by STRING, so this last sentence should say "must" instead of
"might".
--
RmK
John Thingstad <·······@online.no> wrote:
> P� Thu, 03 Apr 2008 03:14:37 +0200, skrev Bob Felts <····@stablecross.com>:
>
> > Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
>
> Perhaps Kent Pitman can enlighten us on the rather obnoxious practice of
> treating nil as "NIL"?
>
Now that I understand the concept of a "string designator" I can see why
string-trim does what it does. So I wouldn't call it obnoxious, but I
might say it was unexpected. (length nil) is nil, not 3. Perhaps if
there were a generic trim, it would do the same thing. As it was, it
caused my code to go into an infinte loop when read-line returned nil,
until I added (and line (string-right-trim '(#\Tab) line)).
····@stablecross.com (Bob Felts) writes:
> John Thingstad <·······@online.no> wrote:
>
>> P� Thu, 03 Apr 2008 03:14:37 +0200, skrev Bob Felts <····@stablecross.com>:
>>
>> > Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
>>
>> Perhaps Kent Pitman can enlighten us on the rather obnoxious practice of
>> treating nil as "NIL"?
>>
>
> Now that I understand the concept of a "string designator" I can see why
> string-trim does what it does. So I wouldn't call it obnoxious, but I
> might say it was unexpected. (length nil) is nil, not 3.
(length nil) --> 0 ; here.
(defun string-length (x) (length (string x)))
(string-length '()) --> 3 ; if you really want 3...
--
__Pascal Bourguignon__
Pascal J. Bourguignon <···@informatimago.com> wrote:
> ····@stablecross.com (Bob Felts) writes:
>
> > John Thingstad <·······@online.no> wrote:
> >
> >> P� Thu, 03 Apr 2008 03:14:37 +0200, skrev Bob Felts <····@stablecross.com>:
> >>
> >> > Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
> >>
> >> Perhaps Kent Pitman can enlighten us on the rather obnoxious practice of
> >> treating nil as "NIL"?
> >>
> >
> > Now that I understand the concept of a "string designator" I can see why
> > string-trim does what it does. So I wouldn't call it obnoxious, but I
> > might say it was unexpected. (length nil) is nil, not 3.
>
> (length nil) --> 0 ; here.
>
>
> (defun string-length (x) (length (string x)))
>
> (string-length '()) --> 3 ; if you really want 3...
I really wanted nil for (string-trim ... nil).
BF> I really wanted nil for (string-trim ... nil).
some people might want 42 for (string-trim ... 42), and what?
it would be illogical for a function that normally returns STRING to return
empty LIST for some inputs. STRINGS are not LISTS.
if you really want NULL to be convertible to empty string, use PHP -- it has
inconsistences of all kinds for you.
Alex Mizrahi <········@users.sourceforge.net> wrote:
> BF> I really wanted nil for (string-trim ... nil).
>
> some people might want 42 for (string-trim ... 42), and what?
>
> it would be illogical for a function that normally returns STRING to return
> empty LIST for some inputs. STRINGS are not LISTS.
> if you really want NULL to be convertible to empty string, use PHP -- it has
> inconsistences of all kinds for you.
All languages are inconsistent. It's the nature of language.
I'll stick with (and line (string-time '(some bag) line))
P� Fri, 04 Apr 2008 14:54:15 +0200, skrev Alex Mizrahi
<········@users.sourceforge.net>:
> BF> I really wanted nil for (string-trim ... nil).
>
> some people might want 42 for (string-trim ... 42), and what?
>
> it would be illogical for a function that normally returns STRING to
> return
> empty LIST for some inputs. STRINGS are not LISTS.
> if you really want NULL to be convertible to empty string, use PHP -- it
> has
> inconsistences of all kinds for you.
>
>
Nice try!
--------------
John Thingstad
····@stablecross.com (Bob Felts) writes:
>
> I really wanted nil for (string-trim ... nil).
IM(inconsequential)O, the interface you want is not unreasonable for
your problem [*], but consider some of the other tradeoffs, given the
rest of the language. The functions with names starting in STRING
guarantee that their return values are strings, and while strings are
vectors and therefore sequences, not all string and vector operations
are sequence operations. So, for example, it's guaranteed that the
return value from STRING-TRIM is suitable as an argument to CHAR,
AREF, ADJUST-ARRAY, and other string and array functions that don't
take lists; and the return value is suitable for use in a form like
(DOTIMES (... (LENGTH ...)) ...) or (LOOP FOR ... ACROSS ...), but
not with DOLIST, (LOOP ... FOR IN ...) or functions that map over
lists, FORMAT's "~{~}" construct, and so on. So holding the rest of
the language constant, if the string functions sometimes returned
lists, you'd have to do type checking around many calls in order to
use their return values properly.
That said, if you want a layer of interface that is insensitive to the
representational types of sequences, you can build one up for yourself
(for the most part, anyway; standard LOOP isn't extensible). For
example, if you want a trimming function for sequences, here's a
simple implementation:
(defun sequence-trim (object-bag sequence &key (test #'eql))
(let* ((start (position object-bag sequence
:test-not (lambda (bag elt)
(find elt bag :test test))))
(end (if start
(position object-bag sequence :from-end t :start start
:test-not (lambda (bag elt)
(find elt bag :test test))))))
(when end (incf end))
(cond ((and start end)
(subseq sequence start end))
(start
(subseq sequence start))
(end
(subseq sequence 0 end))
(t
(subseq sequence 0 0)))))
(sequence-trim "AB" "abcdef" :test 'char-equal)
=> "cdef"
(sequence-trim "ab" nil)
=> NIL
--
RmK
[*] I don't much like the tradeoffs in mixing up any pair of the empty
list, an empty string, and EOF in order to get a general-purpose
iteration construct to stop (which was, I think, your original
problem). For the common case of iterating over lines from a stream,
ISTM that a reasonable DOLINES macro will be handier than a library
that mixes these things up, e.g.,
(defmacro dolines ((line &optional stream return) &body body)
(check-type line symbol)
(let ((streamvar (gensym)))
`(let ((,streamvar ,stream))
(do ((,line (read-line ,streamvar nil 'eof)
(read-line ,streamvar nil 'eof)))
((eql ,line 'eof) ,return)
,@body))))
Note that by expanding into a DO, you get access to all the debatable
qualities of the implicit BLOCK named NIL and implicit TAGBODY:
(dolines (line (make-string-input-stream
(format nil "foo~%quux~%bar~%baz~%ignore~%")))
;; Return from the loop the first line containing the letter #\z.
(when (find #\z line)
(return line))
;; Skip over any lines containing a #\q.
(when (find #\q line)
(go continue))
;; Otherwise, print the line.
(write-line line)
continue)
-| foo
-| bar
=> "baz"
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: string-trim
Date:
Message-ID: <rem-2008apr04-002@yahoo.com>
> From: ····@stablecross.com (Bob Felts)
> I really wanted nil for (string-trim ... nil).
Then you can't use Common Lisp. Try to find some other programming
language that has that behaviour. Or write your own programming
language.
Or build your own package, which inherits from the usual default
package but overrides the definition of string-trim to work the way
*you* want it to work instead of the way the built-in function by
the same name works. With your own package, you can change the
behaviour of as many functions as you want, yet still have all of
Common Lisp available the way it's standardized any time you want.
In article <··························@stablecross.com>,
····@stablecross.com (Bob Felts) wrote:
> I really wanted nil for (string-trim ... nil).
Something like this?
(when thing
(string-trim ... thing))
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
P� Sat, 05 Apr 2008 04:48:12 +0200, skrev Barry Margolin
<······@alum.mit.edu>:
> In article <··························@stablecross.com>,
> ····@stablecross.com (Bob Felts) wrote:
>
>> I really wanted nil for (string-trim ... nil).
>
> Something like this?
>
> (when thing
> (string-trim ... thing))
>
Yes, but why is the behaviour of string< or string-lessp different from <?
--------------
John Thingstad
In article <·················@pandora.alfanett.no>,
"John Thingstad" <·······@online.no> wrote:
> P� Sat, 05 Apr 2008 04:48:12 +0200, skrev Barry Margolin
> <······@alum.mit.edu>:
>
> > In article <··························@stablecross.com>,
> > ····@stablecross.com (Bob Felts) wrote:
> >
> >> I really wanted nil for (string-trim ... nil).
> >
> > Something like this?
> >
> > (when thing
> > (string-trim ... thing))
> >
>
> Yes, but why is the behaviour of string< or string-lessp different from <?
Because it's reasonable to coerce symbols to strings by using their
names, and NIL is a symbol; the correspondence is so obvious that we
made it automatic. There's no analogous correspondence between symbols
and numbers, so functions that expect a number reject symbols as
arguments.
--
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE don't copy me on replies, I'll read them in the group ***
BF> Why does (string-trim '(#\Tab) nil) return "NIL" and not nil?
because it's STRING-trim, it returns STRING and it accepts STRING as
parameter. empty string is "", not NIL and not (), which is empty LIST.
string-trim just converts symbol NIL into string "NIL" that is it's
symbol-name, that's what confuses you.