From: Ernest Smit
Subject: Common Lisp: String to Number conversion
Date: 
Message-ID: <3AD1664B.5E77391A@oce.nl>
Hello,

Does anyone have code for converting a string to number? Note that I do
not use elisp, but common Lisp. 

Thanks in advance,

Greetings,

Ernest

(BTW: Can you please send it directly to me by email?)

From: Kent M Pitman
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <sfw7l0uze53.fsf@world.std.com>
Ernest Smit <····@oce.nl> writes:

> Does anyone have code for converting a string to number? Note that I do
> not use elisp, but common Lisp. 

What kind of number?

Common Lisp's PARSE-INTEGER will convert a string to an integer.
See CLHS for details.

For portable float-parsing, Common Lisp's READ-FROM-STRING will
perform the action of READ on a string.  It is recommended that you
bind *READ-EVAL* to NIL to avoid trojan horses if you use this.
There is also a float-parsing library floating around, somewhere;
see either the ALU web site or the CMU AI repository.

http://www.alu.org/  is a good place to start looking for 
things generally, including the FAQ.
From: Ralf Muschall
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <m3y9t47otn.fsf@mammut.lipsia.de>
Kent M Pitman <······@world.std.com> writes:

> perform the action of READ on a string.  It is recommended that you
> bind *READ-EVAL* to NIL to avoid trojan horses if you use this.

How widespread are such attack?

IIRC xlispstat has no *READ-EVAL* at all and evaluates "#."-stuff
always, but I've never heard about such things (which should be even
more probable with xlispstat which is intended to be run by lusers).

Ralf

-- 
GS d->? s:++>+++ a C++++ UL+++ UH++ P++ L++ E+++ W- N++ o-- K- w--- !O M- V-
PS+>++ PE Y+>++ PGP+ !t !5 !X !R !tv  b+++ DI+++ D?  G+ e++++ h+ r? y?
From: Kent M Pitman
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <sfw3dbcwmvq.fsf@world.std.com>
Ralf Muschall <····@lipsia.de> writes:

> Kent M Pitman <······@world.std.com> writes:
> 
> > perform the action of READ on a string.  It is recommended that you
> > bind *READ-EVAL* to NIL to avoid trojan horses if you use this.
> 
> How widespread are such attack?
 
 (1) It has been done.
 (2) There was no good reason for it to succeed.

But I think in general it is a *bad* question to ask, since whether there
is a danger is not a function of past action.

> IIRC xlispstat has no *READ-EVAL* at all and evaluates "#."-stuff
> always, but I've never heard about such things (which should be even
> more probable with xlispstat which is intended to be run by lusers).

Depends on whether the data stream is open to outside users.  Certainly,
some uses are safe, if the client is provably a nice guy.  But what's the
point in building vulnerable software when it's so easy to make it solid?
From: Patrick A. O'Donnell
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <rtg0f93rnx.fsf@ascent.com>
Ralf Muschall <····@lipsia.de> writes:
> Kent M Pitman <······@world.std.com> writes:
> 
> > perform the action of READ on a string.  It is recommended that you
> > bind *READ-EVAL* to NIL to avoid trojan horses if you use this.
> 
> How widespread are such attack?

I don't know how widespread they are, but check out Scientific
American, Dec 2000, p. 20.
From: Shannon Spires
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <svspire-DF3355.18011220042001@news.sandia.gov>
In article <··············@ascent.com>, ···@ascent.com (Patrick A. 
O'Donnell) wrote:

> Ralf Muschall <····@lipsia.de> writes:
> > Kent M Pitman <······@world.std.com> writes:
> > 
> > > perform the action of READ on a string.  It is recommended that you
> > > bind *READ-EVAL* to NIL to avoid trojan horses if you use this.
> > 
> > How widespread are such attack?
> 
> I don't know how widespread they are, but check out Scientific
> American, Dec 2000, p. 20.
> 

Yes, well, we do try. But even the best of us blow it sometimes.
At least it didn't involve a warship having to be towed back to port ;-)

Shannon Spires
From: Dorai Sitaram
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <9b7cne$306$1@news.gte.com>
In article <·················@oce.nl>, Ernest Smit  <····@oce.nl> wrote:
>Hello,
>
>Does anyone have code for converting a string to number? Note that I do
>not use elisp, but common Lisp. 

If what you want is something like the Scheme
string->number, then the following Common-Lisp
definition should be serviceable.

(defun string-to-number (s &optional (b 10))
  (let ((*read-base* b))
    (let ((n (read-from-string s nil)))
      (if (numberp n) n nil))))

--d
From: Marco Antoniotti
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <y6cd7agzmzr.fsf@octagon.mrl.nyu.edu>
····@goldshoe.gte.com (Dorai Sitaram) writes:

> In article <·················@oce.nl>, Ernest Smit  <····@oce.nl> wrote:
> >Hello,
> >
> >Does anyone have code for converting a string to number? Note that I do
> >not use elisp, but common Lisp. 
> 
> If what you want is something like the Scheme
> string->number, then the following Common-Lisp
> definition should be serviceable.
> 
> (defun string-to-number (s &optional (b 10))
>   (let ((*read-base* b))
>     (let ((n (read-from-string s nil)))
>       (if (numberp n) n nil))))

Slightly better (IHMO)

==============================================================================
* (defun string-to-number (s &optional (b 10))
    (let* ((*read-base* b)
	   (n (read-from-string s nil))
	  )
      (if (numberp n)
	  n
	  (error "String ~S does not contain a NUMBER." s))))
STRING-TO-NUMBER
* (string-to-number "#C(1 101)" 2)
#C(1 5)
* (string-to-number "10/A" 16)
8/5
* (string-to-number "10/A")
Invoking debugger...
==============================================================================

Of course, complex numbers and rationals are available in CL, but not
as readily in other languages. :)

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group	tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA			http://bioinformatics.cat.nyu.edu
	       "Hello New York! We'll do what we can!"
			Bill Murray in `Ghostbusters'.
From: Dorai Sitaram
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <9b7lk1$3bt$1@news.gte.com>
In article <···············@octagon.mrl.nyu.edu>,
Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>
>····@goldshoe.gte.com (Dorai Sitaram) writes:
>> 
>> (defun string-to-number (s &optional (b 10))
>>   (let ((*read-base* b))
>>     (let ((n (read-from-string s nil)))
>>       (if (numberp n) n nil))))
>
>Slightly better (IHMO)
>
>==============================================================================
>* (defun string-to-number (s &optional (b 10))
>    (let* ((*read-base* b)
>	   (n (read-from-string s nil))
>	  )
>      (if (numberp n)
>	  n
>	  (error "String ~S does not contain a NUMBER." s))))
>STRING-TO-NUMBER
>* (string-to-number "#C(1 101)" 2)
>#C(1 5)
>* (string-to-number "10/A" 16)
>8/5
>* (string-to-number "10/A")
>Invoking debugger...
>==============================================================================

This is a less useful procedure.  A number-or-nil
string-to-number allows one to check if a string
represents a number, and then perform one of two
actions based on that check.  

A more useful improvement would be one that ensures
that string-to-number returns nil for strings
like "1600 Pennsylvanie Ave".  

--d
From: Barry Margolin
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <51JB6.429$U4.18341@burlma1-snr2>
In article <············@news.gte.com>,
Dorai Sitaram <····@goldshoe.gte.com> wrote:
>In article <···············@octagon.mrl.nyu.edu>,
>Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>>
>>····@goldshoe.gte.com (Dorai Sitaram) writes:
>>> 
>>> (defun string-to-number (s &optional (b 10))
>>>   (let ((*read-base* b))
>>>     (let ((n (read-from-string s nil)))
>>>       (if (numberp n) n nil))))
>>
>>Slightly better (IHMO)
>>
>>==============================================================================
>>* (defun string-to-number (s &optional (b 10))
>>    (let* ((*read-base* b)
>>	   (n (read-from-string s nil))
>>	  )
>>      (if (numberp n)
>>	  n
>>	  (error "String ~S does not contain a NUMBER." s))))
>>STRING-TO-NUMBER
>>* (string-to-number "#C(1 101)" 2)
>>#C(1 5)
>>* (string-to-number "10/A" 16)
>>8/5
>>* (string-to-number "10/A")
>>Invoking debugger...
>>==============================================================================
>
>This is a less useful procedure.  A number-or-nil
>string-to-number allows one to check if a string
>represents a number, and then perform one of two
>actions based on that check.  

And why can't you do that with the second version, by using an error
handler?

>A more useful improvement would be one that ensures
>that string-to-number returns nil for strings
>like "1600 Pennsylvanie Ave".  

True.  READ-FROM-STRING returns a second value, the number of characters
that were consumed.  If this is not equal to the length of the string, then
you know that there was extraneous text in the string:

(defun string-to-number (s &optional (*read-base* 10))
  (multiple-value-bind (n count)
      (read-from-string s nil)
    (if (and (numberp n)
             (= count (length s)))
        n
        (error "String ~S is not a NUMBER." s))))

-- 
Barry Margolin, ······@genuity.net
Genuity, Burlington, 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: Kent M Pitman
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <sfw4rvswn5l.fsf@world.std.com>
Barry Margolin <······@genuity.net> writes:

> True.  READ-FROM-STRING returns a second value, the number of characters
> that were consumed.  If this is not equal to the length of the string, then
> you know that there was extraneous text in the string:
> 
> (defun string-to-number (s &optional (*read-base* 10))
>   (multiple-value-bind (n count)
>       (read-from-string s nil)
>     (if (and (numberp n)
>              (= count (length s)))
>         n
>         (error "String ~S is not a NUMBER." s))))

Actually, to quote CLHS on the secondary value, position:

 position---an integer greater than or equal to zero, and less than 
  or equal to one more than the length of the string. 

I can't remember why it was allowed to be "one more than", but anyway
a red flag goes up in my brain when people don't do
  (>= pos (length string))

Also, while I'm in there, I want to add a plug for binding *READ-EVAL*
to NIL while doing anything like this that doesn't reuire #. for its
correct function.  No sense inviting trojan horses.
From: Dorai Sitaram
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <9b9oge$4rs$1@news.gte.com>
In article <··················@burlma1-snr2>,
Barry Margolin  <······@genuity.net> wrote:
>In article <············@news.gte.com>,
>Dorai Sitaram <····@goldshoe.gte.com> wrote:
>>
>>This is a less useful procedure.  A number-or-nil
>>string-to-number allows one to check if a string
>>represents a number, and then perform one of two
>>actions based on that check.  
>
>And why can't you do that with the second version, by using an error
>handler?

Of course it is possible, but it is a complicated
way of going about the matter.  A valid-or-nil
procedure doubles as an easy-to-use predicate, and that
is a good thing.  

--d
From: Marco Antoniotti
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <y6c4rvrzbb4.fsf@octagon.mrl.nyu.edu>
····@goldshoe.gte.com (Dorai Sitaram) writes:

> In article <··················@burlma1-snr2>,
> Barry Margolin  <······@genuity.net> wrote:
> >In article <············@news.gte.com>,
> >Dorai Sitaram <····@goldshoe.gte.com> wrote:
> >>
> >>This is a less useful procedure.  A number-or-nil
> >>string-to-number allows one to check if a string
> >>represents a number, and then perform one of two
> >>actions based on that check.  
> >
> >And why can't you do that with the second version, by using an error
> >handler?
> 
> Of course it is possible, but it is a complicated
> way of going about the matter.  A valid-or-nil
> procedure doubles as an easy-to-use predicate, and that
> is a good thing.  

Good point.  Let's get closer to "The Right Thing"....

(defun string-to-number (s &key
			   ((:read-base *read-base*) *read-base*)
			   (parse-error-p t)
			   eof-error-p
			   eof-value)
  (let ((*read-eval* nil))
    (multiple-value-bind (n count)
	(read-from-string s eof-error-p eof-value)
      (if (and (numberp n) (= count (length s)))
	  n
	  (when parse-error-p
	    (error "String ~S is not a NUMBER." s))))))

Not many ways to achieve the same in Scheme.....

Cheers

-- 
Marco Antoniotti ========================================================
NYU Courant Bioinformatics Group	tel. +1 - 212 - 998 3488
719 Broadway 12th Floor                 fax  +1 - 212 - 995 4122
New York, NY 10003, USA			http://bioinformatics.cat.nyu.edu
	       "Hello New York! We'll do what we can!"
			Bill Murray in `Ghostbusters'.
From: Dorai Sitaram
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <9bf2kl$91v$1@news.gte.com>
In article <···············@octagon.mrl.nyu.edu>,
Marco Antoniotti  <·······@cs.nyu.edu> wrote:
>
>Good point.  Let's get closer to "The Right Thing"....
>
>(defun string-to-number (s &key
>			   ((:read-base *read-base*) *read-base*)
>			   (parse-error-p t)
>			   eof-error-p
>			   eof-value)
>  (let ((*read-eval* nil))
>    (multiple-value-bind (n count)
>	(read-from-string s eof-error-p eof-value)
>      (if (and (numberp n) (= count (length s)))
>	  n
>	  (when parse-error-p
>	    (error "String ~S is not a NUMBER." s))))))
>
>Not many ways to achieve the same in Scheme.....

Actually, I am now persuaded that my valid-or-nil
approach may not be all that useful in Common Lisp.
Without a cond syntax that can exploit them,
valid-or-nil procedures have much less going for
them than I implied.  Eg,

(cond ...                                    ; *wrong*
      ((valid-or-nil-procedure its-args) => 
         #'(lambda (non-nil-result)
             (do-something-with non-nil-result)))
      ...)

(It isn't that this kind of thing isn't possible in CL
too, but built-in syntax and usage are not behind it.)

--d
From: Kent M Pitman
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <sfwd7acetvk.fsf@world.std.com>
····@goldshoe.gte.com (Dorai Sitaram) writes:

> Actually, I am now persuaded that my valid-or-nil
> approach may not be all that useful in Common Lisp.
> Without a cond syntax that can exploit them,
> valid-or-nil procedures have much less going for
> them than I implied.  Eg,
> 
> (cond ...                                    ; *wrong*
>       ((valid-or-nil-procedure its-args) => 
>          #'(lambda (non-nil-result)
>              (do-something-with non-nil-result)))
>       ...)

Not necessarily.  First, the valid-or-nil thing is still quite useful
in the case of (or (parse-float foo) (error "Not a float: ~S" foo)).

Further, both the total text involved in doing the following seems
not materially different than what you have to do in Scheme (and
gets to be a lot less if you get to re-use the temp variable more than
once since you can share the setup.)

  (let (val)
    (cond ((setq val (valid-or-nil-procedure its-args))
           (do-something-with val))
          ...))

Not to mention the fact that CL doesn't exactly keep you from extending
COND to do what you want.  Either you can call it KOND or you can shadow
COND.

In spite of the supposed cuteness of the syntax in Scheme, I never really
got into using it a whole lot.  Fortunately, the need to use it doesn't
seem to me to come up much in either language, since most often there are
other transformations that have to be done, too.

I've had to write the above let only about 5 times in my career, I'd
bet, and yet I write and productively use valid-or-nil kinds of things
all the time. Not much of a stat, I suppose, since it's both personal
and anecdotal.  Even so, it makes me think this is not a large issue.

Btw, I often have these false-or-value things yield two values, NIL
and string failure message, when they fail.  That lets them be used in
even more circumstances, plus is informative in debugging even if it's
never used in code.
From: Dorai Sitaram
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <9bf795$95i$1@news.gte.com>
In article <···············@world.std.com>,
Kent M Pitman  <······@world.std.com> wrote:
>····@goldshoe.gte.com (Dorai Sitaram) writes:
>
>> Actually, I am now persuaded that my valid-or-nil
>> approach may not be all that useful in Common Lisp.
>> Without a cond syntax that can exploit them,
>> valid-or-nil procedures have much less going for
>> them than I implied.  Eg,
>> 
>> (cond ...                                    ; *wrong*
>>       ((valid-or-nil-procedure its-args) => 
>>          #'(lambda (non-nil-result)
>>              (do-something-with non-nil-result)))
>>       ...)
>
>Not necessarily. ...
>
>... both the total text involved in doing the following seems
>not materially different than what you have to do in Scheme (and
>gets to be a lot less if you get to re-use the temp variable more than
>once since you can share the setup.)
>
>  (let (val)
>    (cond ((setq val (valid-or-nil-procedure its-args))
>           (do-something-with val))
>          ...))

That is certainly neat.  I wish I'd thought of it. 
Thank you.

--d
From: Barry Margolin
Subject: Re: Common Lisp: String to Number conversion
Date: 
Message-ID: <0BEC6.437$U4.18931@burlma1-snr2>
In article <············@news.gte.com>,
Dorai Sitaram <····@goldshoe.gte.com> wrote:
>Of course it is possible, but it is a complicated
>way of going about the matter.  A valid-or-nil
>procedure doubles as an easy-to-use predicate, and that
>is a good thing.  

It's easy to turn a signalling procedure into a valid-or-nil procedure by
wrapping the call in IGNORE-ERRORS.

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