From: Andy Chambers
Subject: splicing with subst
Date: 
Message-ID: <1177677746.569192.16940@b40g2000prd.googlegroups.com>
Hi,

I'd like to transform a tree such that a marker sexp is replaced by an
inline list of sexp's.  For example....

'(list
   (string)
   (marker))

should be replaced with....

'(list
  (string)
  (one) (two) (three))

I tried using subst, but the nearest I could transform it to is....

'(list
  (string)
  ((one) (two) (three)))

...which is no good for context in which it is needed.  Is there some
subst recipe to do this?

---Andy

From: Giorgos Pontikakis
Subject: Re: splicing with subst
Date: 
Message-ID: <87y7kdrgiv.fsf@artemis.extherm.gr>
Andy Chambers <··············@googlemail.com> writes:

> Hi,
>
> I'd like to transform a tree such that a marker sexp is replaced by an
> inline list of sexp's.  For example....
>
> '(list
>    (string)
>    (marker))
>
> should be replaced with....
>
> '(list
>   (string)
>   (one) (two) (three))
>
> I tried using subst, but the nearest I could transform it to is....
>
> '(list
>   (string)
>   ((one) (two) (three)))
>
> ...which is no good for context in which it is needed.  Is there some
> subst recipe to do this?
>
> ---Andy

Hi, 

This seems to work:

(defparameter *tree* (list 'list '(string) '(marker)))
--> *TREE*

*tree*
--> (LIST (STRING) (MARKER))

(subst (list '(one) '(two) '(three)) '((marker)) *tree* :test #'equalp)
--> (LIST (STRING) (ONE) (TWO) (THREE))

Hope this helps,
-- Giorgos
From: Alan Crowe
Subject: Re: splicing with subst
Date: 
Message-ID: <86hcr1sknv.fsf@cawtech.freeserve.co.uk>
Giorgos Pontikakis <···@freemail.gr> writes:

> Andy Chambers <··············@googlemail.com> writes:
> 
> > Hi,
> >
> > I'd like to transform a tree such that a marker sexp is replaced by an
> > inline list of sexp's.  For example....
> >
> > '(list
> >    (string)
> >    (marker))
> >
> > should be replaced with....
> >
> > '(list
> >   (string)
> >   (one) (two) (three))
> >
> > I tried using subst, but the nearest I could transform it to is....
> >
> > '(list
> >   (string)
> >   ((one) (two) (three)))
> >
> > ...which is no good for context in which it is needed.  Is there some
> > subst recipe to do this?
> >
> > ---Andy
> 
> Hi, 
> 
> This seems to work:
> 
> (defparameter *tree* (list 'list '(string) '(marker)))
> --> *TREE*
> 
> *tree*
> --> (LIST (STRING) (MARKER))
> 
> (subst (list '(one) '(two) '(three)) '((marker)) *tree* :test #'equalp)
> --> (LIST (STRING) (ONE) (TWO) (THREE))
> 
> Hope this helps,
> -- Giorgos

That is very clever, but I think it is limited to the case
when the marker is the final item in the list, and uses the
fact that subst really works on cons trees rather than
lists.

I don't think any of the built-in's do the splicing that the
original poster is seeking, so he will need to write his
own, something like

CL-USER> (defun splice (replacement target data test)
           (typecase data
             (atom data)
             (list (mapcan (lambda(item)
                             (if (funcall test item target)
                                 (copy-list replacement)
                                 (list (splice replacement
                                               target
                                               item
                                               test))))
                           data))))
SPLICE

CL-USER> (splice '(one two three) 'marker 
                 '(the (count marker) is (just (a count marker and no more)))
                 #'eql)
(THE (COUNT ONE TWO THREE) IS (JUST (A COUNT ONE TWO THREE AND NO MORE)))

but swapped round abit to make sure that the initial data is
also matched against the target.

Alan Crowe
Edinburgh
Scotland
From: Madhu
Subject: Re: splicing with subst
Date: 
Message-ID: <m3647h6qfv.fsf@robolove.meer.net>
* Alan Crowe  <··············@cawtech.freeserve.co.uk> :
| Giorgos Pontikakis <···@freemail.gr> writes:
|> (defparameter *tree* (list 'list '(string) '(marker)))
|> (subst (list '(one) '(two) '(three)) '((marker)) *tree* :test #'equalp)
|
| That is very clever, but I think it is limited to the case
| when the marker is the final item in the list, and uses the
| fact that subst really works on cons trees rather than
| lists.
|
| I don't think any of the built-in's do the splicing that the
| original poster is seeking, so he will need to write his
| own, something like

[solution elided]

But couln't you use SUBST if you got hold of the cons to replace?

(defun find-cons-containing (list symbol)
  (if (consp list)
      (if (consp (car list))
          (if (eql symbol (caar list))
              (car list)
            (or (find-cons-containing (cdar list) symbol)
                (find-cons-containing (cdr list) symbol)))
        (if (eql (car list) symbol)
            list
          (find-cons-containing (cdr list) symbol)))
    (if (eql symbol list) (error "unexpected marker"))))

[untested]

while (FIND-CONS-CONTANING LIST 'LIST-MARKER) returned non-NIL you
could call probably call SUBST, in a loop perhaps like:

(defun splice (replacement marker tree)
  "My eyes, My eyes!"
  (loop for x = (find-cons-containing tree marker)
        while x do (setq tree (subst (append replacement (cdr x)) x tree)))
  tree)

Your solution is of course preferable :)

--
Madhu
From: Madhu
Subject: Re: splicing with subst
Date: 
Message-ID: <m3wszx5bfe.fsf@robolove.meer.net>
* Madhu <·······@meer.net> <··············@robolove.meer.net> :
| * Alan Crowe  <··············@cawtech.freeserve.co.uk> :
| | Giorgos Pontikakis <···@freemail.gr> writes:
| |> (defparameter *tree* (list 'list '(string) '(marker)))
| |> (subst (list '(one) '(two) '(three)) '((marker)) *tree* :test #'equalp)
| |
| | That is very clever, but I think it is limited to the case
| | when the marker is the final item in the list, and uses the
| | fact that subst really works on cons trees rather than
| | lists.
| |
| | I don't think any of the built-in's do the splicing that the
| | original poster is seeking, so he will need to write his
| | own, something like
|
| [solution elided]
|
| But couln't you use SUBST if you got hold of the cons to replace?
|
| (defun find-cons-containing (list symbol)
|   (if (consp list)
|       (if (consp (car list))
|           (if (eql symbol (caar list))
|               (car list)
|             (or (find-cons-containing (cdar list) symbol)
|                 (find-cons-containing (cdr list) symbol)))
|         (if (eql (car list) symbol)
|             list
|           (find-cons-containing (cdr list) symbol)))
|     (if (eql symbol list) (error "unexpected marker"))))
|
| [untested]
|
| while (FIND-CONS-CONTANING LIST 'LIST-MARKER) returned non-NIL you
| could call probably call SUBST, in a loop perhaps like:
|
| (defun splice (replacement marker tree)
|   "My eyes, My eyes!"
|   (loop for x = (find-cons-containing tree marker)
|         while x do (setq tree (subst (append replacement (cdr x)) x tree)))
|   tree)

That bit of ugliness was unwarranted:

(defun splice (replacement marker tree)
  (let ((x (find-cons-containing tree marker)))
    (if x
        (subst (append replacement (splice replacement marker (cdr x))) x tree)
        tree)))

|
| Your solution is of course preferable :)
--
Madhu
From: Pascal Bourguignon
Subject: Re: splicing with subst
Date: 
Message-ID: <87vefhn47j.fsf@thalassa.lan.informatimago.com>
Andy Chambers <··············@googlemail.com> writes:

> Hi,
>
> I'd like to transform a tree such that a marker sexp is replaced by an
> inline list of sexp's.  For example....
>
> '(list
>    (string)
>    (marker))
>
> should be replaced with....
>
> '(list
>   (string)
>   (one) (two) (three))

Why do you have this form:  (quote (list (string) (marker)))

It's really strange to have quote in data lists.  Usually, you just
put directly the data you want.


If you mean that you have actually some program, then what's wrong
with backquote and comma-at?

(flet ((marker () (list '(one) '(two) '(three))))
  `(list (string) ,@(marker)))

Well this gives: (LIST (STRING) (ONE) (TWO) (THREE))
since you want a quote:


(flet ((marker () (list '(one) '(two) '(three))))
  `(quote (list (string) ,@(marker))))
--> '(LIST (STRING) (ONE) (TWO) (THREE))



> I tried using subst, but the nearest I could transform it to is....
>
> '(list
>   (string)
>   ((one) (two) (three)))
>
> ...which is no good for context in which it is needed.  Is there some
> subst recipe to do this?

You could write your own unsplicing substitution, if you don't want to
use ` and ,@:

(defun unsplice-subst (new old tree &key (test (function eql)))
  (cond
    ((atom tree) tree)
    ((funcall test old (car tree))
     (append new (unsplice-subst new old (cdr tree) :test test)))
    (t (cons (unsplice-subst new old (car tree) :test test)
             (unsplice-subst new old (cdr tree) :test test)))))

(unsplice-subst '((one) (two) (three))
                '(marker)
                '((marker) 1 2 (3 (marker) 4) 5 6 (marker))
                :test (function equal))
--> ((ONE) (TWO) (THREE) 1 2 (3 (ONE) (TWO) (THREE) 4) 5 6 (ONE) (TWO) (THREE))



(unsplice-subst '((ONE) (TWO) (THREE))
                           '(marker)
                           ''(list (string) (marker))
                           :test (function equal))
--> '(LIST (STRING) (ONE) (TWO) (THREE))


(See how you need to write two quotes in the program to get one quote
in the result data?)

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

WARNING: This product warps space and time in its vicinity.
From: Andy Chambers
Subject: Re: splicing with subst
Date: 
Message-ID: <1177787102.598798.112570@y5g2000hsa.googlegroups.com>
On Apr 27, 5:59 pm, Pascal Bourguignon <····@informatimago.com> wrote:
> Andy Chambers <··············@googlemail.com> writes:
> > Hi,
>
> > I'd like to transform a tree such that a marker sexp is replaced by an
> > inline list of sexp's.  For example....
>
> > '(list
> >    (string)
> >    (marker))
>
> > should be replaced with....
>
> > '(list
> >   (string)
> >   (one) (two) (three))
>
> Why do you have this form:  (quote (list (string) (marker)))

I'm trying to make an emacs widget that has a bunch of fields and a
checklist, the elements of which are determined at runtime.  I thought
a nice way of doing it would be to put a marker sexp where the
checklist is supposed to go, then subst it in the convert-widget
function.

A checklist form has the format....

(checklist :format "Select from\n\n" (const "one") (const "two"))

...so my actual problem (which was maybe simple enough to quote
directly instead of trying to contrive an abstract example of the
problem) is to translate this....

'(list
   (string :tag "OID")
   (string :tag "Name")
   (item-refs))

...into this

'(list
   (string :tag "OID")
   (string :tag "Name")
   (checklist :format "Select from\n\n" (const "item ref 1") (const
"item ref 2")))


> It's really strange to have quote in data lists.  Usually, you just
> put directly the data you want.
>
> If you mean that you have actually some program, then what's wrong
> with backquote and comma-at?
>
> (flet ((marker () (list '(one) '(two) '(three))))
>   `(list (string) ,@(marker)))

That seems like a nice way of doing it but I can't think of a way it
would work.  I suppose the (item-refs) bit is code but the surrounding
widget specification is data.  I can't eval (item-refs) when the
widget is defined because its value depends on runtime data.

The only runtime hook I have is the convert-widget function that gets
called when the widget is created.  At this point, I can access the
widget specification as data and mutate it into whatever is required.

Thankyou everyone for the splicing suggestions.  I'll need to take
some time to digest them but they seem to do  the job.  I really
appreciate you taking the time to help.

--Andy
From: Pascal Bourguignon
Subject: Re: splicing with subst
Date: 
Message-ID: <878xcckyw6.fsf@thalassa.lan.informatimago.com>
Andy Chambers <··············@googlemail.com> writes:

> On Apr 27, 5:59 pm, Pascal Bourguignon <····@informatimago.com> wrote:
>> Andy Chambers <··············@googlemail.com> writes:
>> > Hi,
>>
>> > I'd like to transform a tree such that a marker sexp is replaced by an
>> > inline list of sexp's.  For example....
>>
>> > '(list
>> >    (string)
>> >    (marker))
>>
>> > should be replaced with....
>>
>> > '(list
>> >   (string)
>> >   (one) (two) (three))
>>
>> Why do you have this form:  (quote (list (string) (marker)))

The question was some nitpicking on my part about why did you write
           '(list (string) (marker)) 
instead of: (list (string) (marker)) 
when you spoke of data.

If you say that you have a list '(a b c)
it means you have a list of two elements, quote and (a b c),
since '(a b c) is equivalent to (quote (a b c))
                                ^  ^   ^
                                |  |   |
                                |  |   +--- second element
                                |  +--------first element
                                +-----------a list

Try:

C/USER[57]> (length (read)) ; you enter this program
'(a b c)                    ; then you enter this data

2                           ; and you get this result.


To put a list '(a b c) in a program, to avoid it being evaluated you
have to quote once more:



C/USER[59]> (let ((x ''(a b c)))
              (print (length x))
              (print (first x))
              (print (second x))
              x)

2                           ; printed
QUOTE                       ; printed
(A B C)                     ; printed
'(A B C)                    ; result, printed by the REPL; 
                            ; this is a list of 2 elements:

C/USER[60]> (length *)
2 


(a b c) would be equal to the list returned as result of the
evaluation of the form '(a b c) or (quote (a b c)).

So you could say that you have the list resulting from '(a b c),
and this would be understood as being (a b c).

But '(a b c) itself is a list (data), as any non atomic form, and it
_is_ the list containing only quote and (a b c).  On the other hand,
'(a b c) is a form (program), which can be _evaluated_ and which would
return the list (a b c).  Note that if a was the name of a function,
and b and c the names of variables, (a b c) would also be a form, that
could also be evaluated...


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"This statement is false."            In Lisp: (defun Q () (eq nil (Q)))