From: Dan Bensen
Subject: register-groups-bind binds to simple arrays
Date: 
Message-ID: <eusdv3$oqm$1@wildfire.prairienet.org>
*or*
When is a string not a string?

With this code (and cl-ppcre loaded):

(let ((mystr (read-line)))
   (register-groups-bind
    (substr) ("([a-zA-Z]+)" mystr)
    (let ((c0 (FOO substr 0)))
      (format t "First char is ~C~%" c0))))

sbcl issues a warning if FOO is aref, char,
schar, or svref.  Only elt compiles silently.
According to type-of, substr is bound to a
simple-array character of whatever length.
With aref:

; caught WARNING:
;   The binding of ARRAY is not a ARRAY:
;     NIL
;   See also:
;     The SBCL Manual, Node "Handling of Types"

The manual didn't help much.

My questions are (a) how come substr isn't some type
of string, or if it is, why is the compiler warning
about char and schar? (b) is elt the preferred accessor
for simple arrays, and if so, why? and (c) is it
standard practice to use elt to access strings bound by
register-groups-bind?

-- 
Dan
www.prairienet.org/~dsb/

From: Zach Beane
Subject: Re: register-groups-bind binds to simple arrays
Date: 
Message-ID: <m3tzvxfvzv.fsf@unnamed.xach.com>
Dan Bensen <··········@cyberspace.net> writes:

> *or*
> When is a string not a string?
> 
> With this code (and cl-ppcre loaded):
> 
> (let ((mystr (read-line)))
>    (register-groups-bind
>     (substr) ("([a-zA-Z]+)" mystr)
>     (let ((c0 (FOO substr 0)))
>       (format t "First char is ~C~%" c0))))
> 
> sbcl issues a warning if FOO is aref, char,
> schar, or svref.  Only elt compiles silently.
> According to type-of, substr is bound to a
> simple-array character of whatever length.

REGISTER-GROUPS-BIND works like so:

  Evaluates statement* with the variables in var-list bound to the
  corresponding register groups after target-string has been matched
  against regex, i.e. each variable is either bound to a string or to
  NIL.

What if (read-line) returns "$$$$"? In that case, SUBSTR will be bound
to NIL, and CHAR (or aref, or schar) would be an error.

I'm not sure why it's a full error (I don't understand the specified
semantics well enough), but you can avoid it in SBCL by
conditionalizing the call:

   (when substr
     (let ((c0 (char substr 0)))
       ...))

That will ensure that CHAR will never be called on NIL.

Zach
From: Zach Beane
Subject: Re: register-groups-bind binds to simple arrays
Date: 
Message-ID: <m3ps6lfvtx.fsf@unnamed.xach.com>
Zach Beane <····@xach.com> writes:

> What if (read-line) returns "$$$$"? In that case, SUBSTR will be bound
> to NIL, and CHAR (or aref, or schar) would be an error.

Oops. I see now that REGISTER-GROUPS-BIND doesn't evaluate its body
when the pattern doesn't match at all. Still, you can avoid the full
warning with conditionalization. Might be worth discussiong on
sbcl-devel.

Zach
From: Dan Bensen
Subject: Re: register-groups-bind binds to simple arrays
Date: 
Message-ID: <ev0jeg$493$1@wildfire.prairienet.org>
Zach Beane wrote:
> Zach Beane <····@xach.com> writes:
>> What if (read-line) returns "$$$$"? In that case, SUBSTR will be bound
>> to NIL, and CHAR (or aref, or schar) would be an error.
> Oops. I see now that REGISTER-GROUPS-BIND doesn't evaluate its body
> when the pattern doesn't match at all. Still, you can avoid the full
> warning with conditionalization. Might be worth discussiong on
> sbcl-devel.

If the variable list is too long, the excess variables get bound to nil.
But the test that makes that decision is applied to every variable,
including the first ones, which I thought would be guaranteed to match
as long as there's an overall match to the target string.

So it looks like the compiler is warning about the non-matching branch
of that IF code in the macro.  I guess you're right that it's always
best to test the array|string first before trying to access it.
sbcl looks like it's working correctly.

-- 
Dan
www.prairienet.org/~dsb/