Lisp HUG Maillist Archive

two functions; which one is in the lisp way?

Greetings Lispers!

I needed a function which checks if a string has a string integer representation. I did two version for it:

(defun string-integer-p (str)
  (when (or (char= #\- (char str 0))
            (char= #\+ (char str 0)))
    (setq str (subseq str 1)))
  (= (length str)
     (count-if #'digit-char-p str)))

(defun string-integer-p (str)
  (handler-case (progn (parse-integer str) t)
    (error () nil)))


And now I'm just curious :), which one is in the lisp way? When compiled in LW6 their execution time is the same, but the last one takes less memory based on (time ...). Which one to use? Or maybe there is a standard function in the standard that I've missed? 


Best,
 Art


Re: two functions; which one is in the lisp way?


Am 25.11.2010 um 23:20 schrieb Art Obrezan:

> 
> Greetings Lispers!
> 
> I needed a function which checks if a string has a string integer representation. I did two version for it:
> 
> (defun string-integer-p (str)
>  (when (or (char= #\- (char str 0))
>            (char= #\+ (char str 0)))
>    (setq str (subseq str 1)))
>  (= (length str)
>     (count-if #'digit-char-p str)))
> 
> (defun string-integer-p (str)
>  (handler-case (progn (parse-integer str) t)
>    (error () nil)))
> 
> 
> And now I'm just curious :), which one is in the lisp way? When compiled in LW6 their execution time is the same, but the last one takes less memory based on (time ...). Which one to use? Or maybe there is a standard function in the standard that I've missed? 

How about:

(defun string-integer-p (str)
  (= (length str) (nth-value 1 (parse-integer str :junk-allowed t))))	

--
Jochen Schmidt
CRISPYLOGICS
Cross Media Solutions
Uhlandstr. 9, 90408 Nürnberg

Telefon +49 (0)911 517 999 82
Telefax +49 (0)911 517 999 83

mailto:info@crispylogics.com
http://www.crispylogics.com





Re: two functions; which one is in the lisp way?

> How about:
> 
> (defun string-integer-p (str)
>   (= (length str) (nth-value 1 (parse-integer str
> :junk-allowed t))))    

Thanks. The speed is the same, but it seems that it has a little bit less memory allocations that the version with handler-case and to me it looks like it is a better version over my first function. But my question is still there: which function is more "lispy": the one with handler-case or the ones without? :)

Best,
 Art


Re: two functions; which one is in the lisp way?

>>>>> On Thu, 25 Nov 2010 14:43:40 -0800 (PST), Art Obrezan said:
> 
> > How about:
> > 
> > (defun string-integer-p (str)
> >   (= (length str) (nth-value 1 (parse-integer str
> > :junk-allowed t))))    
> 
> Thanks. The speed is the same, but it seems that it has a little bit less
> memory allocations that the version with handler-case and to me it looks
> like it is a better version over my first function. But my question is still
> there: which function is more "lispy": the one with handler-case or the ones
> without? :)

It depends what you mean by lispy.  I would say that the version using
count-if is just weird :-)

You could do it directly:

(defun string-integer-p (str)
  (do* ((limit (length str))
        (index (case (and (> limit 0) (char str 0))
                 ((#\- #\+) 1)
                 (t 0))
               (1+ index)))
       ((>= index limit) t)
    (unless (digit-char-p (char str index))
      (return nil))))

-- 
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/


Re: two functions; which one is in the lisp way?

Hi Art,

The second version definitely looks more elegant to me, but how about
this?

(defun string-integer-p (str)
    (integerp (parse-integer str :junk-allowed t)))


Cheers,
James


On Thu, 25 Nov 2010 14:20 -0800, "Art Obrezan" <artobrezan@yahoo.com>
wrote:
> 
> Greetings Lispers!
> 
> I needed a function which checks if a string has a string integer
> representation. I did two version for it:
> 
> (defun string-integer-p (str)
>   (when (or (char= #\- (char str 0))
>             (char= #\+ (char str 0)))
>     (setq str (subseq str 1)))
>   (= (length str)
>      (count-if #'digit-char-p str)))
> 
> (defun string-integer-p (str)
>   (handler-case (progn (parse-integer str) t)
>     (error () nil)))
> 
> 
> And now I'm just curious :), which one is in the lisp way? When compiled
> in LW6 their execution time is the same, but the last one takes less
> memory based on (time ...). Which one to use? Or maybe there is a
> standard function in the standard that I've missed? 
> 
> 
> Best,
>  Art
> 
> 




Re: two functions; which one is in the lisp way?

> The second version definitely looks more elegant to me, but
> how about this?
> 
> (defun string-integer-p (str)
>     (integerp (parse-integer str :junk-allowed t)))

No, it doesn't work, it has t for this (string-integer-p "123a") which isn't true.

Best,
 Art


Re: two functions; which one is in the lisp way?

Hi,

Personally I like the second one best. I've actually done a very similar 
function, just added an optional parameter to set the value on error and 
I believe I didn't handle 'ERROR because I thought it was a too generic 
error. I think it's a lot more concise and easier to follow.

Just my personal opinion,

Alex Paes


On 11/25/2010 10:20 PM, Art Obrezan wrote:
>
> Greetings Lispers!
>
> I needed a function which checks if a string has a string integer representation. I did two version for it:
>
> (defun string-integer-p (str)
>    (when (or (char= #\- (char str 0))
>              (char= #\+ (char str 0)))
>      (setq str (subseq str 1)))
>    (= (length str)
>       (count-if #'digit-char-p str)))
>
> (defun string-integer-p (str)
>    (handler-case (progn (parse-integer str) t)
>      (error () nil)))
>
>
> And now I'm just curious :), which one is in the lisp way? When compiled in LW6 their execution time is the same, but the last one takes less memory based on (time ...). Which one to use? Or maybe there is a standard function in the standard that I've missed?
>
>
> Best,
>   Art
>


Re: two functions; which one is in the lisp way?

Art Obrezan <artobrezan@yahoo.com> writes:

> Greetings Lispers!
>
> I needed a function which checks if a string has a string integer
> representation. I did two version for it: 
>
> (defun string-integer-p (str)
>   (when (or (char= #\- (char str 0))
>             (char= #\+ (char str 0)))
>     (setq str (subseq str 1)))
>   (= (length str)
>      (count-if #'digit-char-p str)))
>
> (defun string-integer-p (str)
>   (handler-case (progn (parse-integer str) t)
>     (error () nil)))

If you want to ignore all errors (which is probably not a good idea),
and count on the fact that all values accept nil are true, your second
implementation can simply be written as: 

CL-USER 12 > (defun string-integer-p (string)
               (ignore-errors (parse-integer string)))
STRING-INTEGER-P

CL-USER 13 > (string-integer-p "123")
123
3

CL-USER 14 > (string-integer-p "123a")
NIL
#<CONDITIONS::SIMPLE-PARSE-ERROR 40200D2303>

CL-USER 15 > (string-integer-p 'foo)
NIL
#<CONDITIONS:TYPE-ERROR-FUNCTION 40200D38EB>


But now you simply get false for non-string values. Your problem
specification is not clear on which values are valid. It is probably
better to specify which errors are acceptable:

CL-USER 16 > (defun string-integer-p (string)
               (handler-case (parse-integer string)
                 (parse-error () nil)))
STRING-INTEGER-P

CL-USER 17 > (string-integer-p "123")
123
3

CL-USER 18 > (string-integer-p "123a")
NIL

CL-USER 19 > (string-integer-p 'foo)

Error: In a call to PARSE-INTEGER: FOO is not of type STRING.
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

Type :b for backtrace or :c <option number> to proceed.
Type :bug-form "<subject>" for a bug report template or :? for other options.


> And now I'm just curious :), which one is in the lisp way?

I prefer the first one because it is simpler/shorter.


> When compiled in LW6 their execution time is the same, but the last
> one takes less memory based on (time ...). Which one to use?

http://en.wikipedia.org/wiki/Program_optimization#When_to_optimize


> Or maybe there is a standard function in the standard that I've
> missed?

No, but LispWorks' hcl:parse-float
(http://www.lispworks.com/documentation/lw60/LW/html/lw-760.htm#pgfId-1344703)
may also be relevant.

Also see The Common Lisp Cookbook chapter on strings
(http://cl-cookbook.sourceforge.net/strings.html#number)

Marco Antoniotti came up with the function below, which was posted in
comp.lang.lisp. I have it in my utility package. It works for all
numbers not just integers. 
(http://groups.google.com/group/comp.lang.lisp/browse_frm/thread/bea3017cadc263ef/532baea05822dc41) 

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

Nico


Re: two functions; which one is in the lisp way?

Nico de Jager <ndj@bitart.cc> writes:

> If you want to ignore all errors (which is probably not a good idea),
> and count on the fact that all values accept nil are true, your second
                                        ^^^^^^
                                        except
Apologies to the pedants :-)


Re: two functions; which one is in the lisp way?


(defun string-integer-p (str)
    (not (null (ignore-errors (parse-intger str)))))


On Nov 25, 2010, at 23:20 , Art Obrezan wrote:

> 
> Greetings Lispers!
> 
> I needed a function which checks if a string has a string integer representation. I did two version for it:
> 
> (defun string-integer-p (str)
>  (when (or (char= #\- (char str 0))
>            (char= #\+ (char str 0)))
>    (setq str (subseq str 1)))
>  (= (length str)
>     (count-if #'digit-char-p str)))
> 
> (defun string-integer-p (str)
>  (handler-case (progn (parse-integer str) t)
>    (error () nil)))
> 
> 
> And now I'm just curious :), which one is in the lisp way? When compiled in LW6 their execution time is the same, but the last one takes less memory based on (time ...). Which one to use? Or maybe there is a standard function in the standard that I've missed? 
> 
> 
> Best,
> Art
> 
> 

--
Marco Antoniotti



Updated at: 2020-12-10 08:38 UTC