From: Jimmy Miller
Subject: Setting subsets of a string
Date: 
Message-ID: <5ab6ec6c-e368-4e98-9ac4-bdd04e878a42@s16g2000vbp.googlegroups.com>
I'd like to write a function to remove subsets of a string by using
destructive updates internally, but then returning the new updated
version of the string, so the function still operates without any side-
effects.  This is what I have right now:

(defun remove-subsets (subsets string)
  (mapcar #'(lambda (sub) (setf (subseq string (car sub) (cdr sub))
""))
	  subsets)
  string)

Unfortunately, it seems as though this function isn't having any
effect, eg:

(setf x "abcdef")
(remove-subsets (list (cons 1 2)) x) => "abcdef"

So, my question is, why are the calls to setf in remove-subsets
seemingly doing nothing?  I assume it has something to do with the
fact that they're being called from within a lambda, but since the
variable string is free in the lambda, shouldn't it be modifying the
copy of the string that is available to the whole function?

Thanks for any help.

From: Tim Bradshaw
Subject: Re: Setting subsets of a string
Date: 
Message-ID: <2009062714073843658-tfb@tfeborg>
On 2009-06-27 13:50:40 +0100, Jimmy Miller <··············@gmail.com> said:

> I'd like to write a function to remove subsets of a string by using
> destructive updates internally, but then returning the new updated
> version of the string, so the function still operates without any side-
> effects.  This is what I have right now:
> 
> (defun remove-subsets (subsets string)
>   (mapcar #'(lambda (sub) (setf (subseq string (car sub) (cdr sub))
> ""))
> 	  subsets)
>   string)

If this function worked, it would have side-effects: in particular it 
would side-effect the string which is its argument, since (SETF SUBSEQ) 
is defined to do that.  However, if you check the specification you 
will find this:

setf may be used with subseq to destructively replace elements of a 
subsequence with elements taken from a sequence of new values. If the 
subsequence and the new sequence are not of equal length, the shorter 
length determines the number of elements that are replaced. The 
remaining elements at the end of the longer sequence are not modified 
in the operation.

Or in other words, since, for your function, "the shorter length" is 
zero, no elements are modified.

The right approach do do what you want to do is almost certainly to cop 
the bits of the string you *do* want.
From: Jimmy Miller
Subject: Re: Setting subsets of a string
Date: 
Message-ID: <0ef63cd9-81fb-4e3a-87c2-327f548f2079@f16g2000vbf.googlegroups.com>
On Jun 27, 9:07 am, Tim Bradshaw <····@tfeb.org> wrote:
> On 2009-06-27 13:50:40 +0100, Jimmy Miller <··············@gmail.com> said:
>
> > I'd like to write a function to remove subsets of a string by using
> > destructive updates internally, but then returning the new updated
> > version of the string, so the function still operates without any side-
> > effects.  This is what I have right now:
>
> > (defun remove-subsets (subsets string)
> >   (mapcar #'(lambda (sub) (setf (subseq string (car sub) (cdr sub))
> > ""))
> >      subsets)
> >   string)
>
> If this function worked, it would have side-effects: in particular it
> would side-effect the string which is its argument, since (SETF SUBSEQ)
> is defined to do that.  However, if you check the specification you
> will find this:
>
> setf may be used with subseq to destructively replace elements of a
> subsequence with elements taken from a sequence of new values. If the
> subsequence and the new sequence are not of equal length, the shorter
> length determines the number of elements that are replaced. The
> remaining elements at the end of the longer sequence are not modified
> in the operation.
>
> Or in other words, since, for your function, "the shorter length" is
> zero, no elements are modified.
>
> The right approach do do what you want to do is almost certainly to cop
> the bits of the string you *do* want.

Well, that certainly clears things up.  Thanks for the advice.
From: Pascal J. Bourguignon
Subject: Re: Setting subsets of a string
Date: 
Message-ID: <873a9lwqg4.fsf@galatea.local>
Jimmy Miller <··············@gmail.com> writes:

> I'd like to write a function to remove subsets of a string by using
> destructive updates internally, but then returning the new updated
> version of the string, so the function still operates without any side-
> effects.  This is what I have right now:
> [...]

You can more easily implement this function without side-effect if you
concentrate on keeping the sub-sequence that are not to be removed.

-- 
__Pascal Bourguignon__