[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon Jan 3 12:06:36 2002 
Subject:The #| |# construct (Was: Have I hit a bug already?) 
From:Aaron Sloman See text for reply address 
Volume-ID:1020103.01 

[To reply replace "Aaron.Sloman.XX" with "A.Sloman"]

pete@jwgibbs.cchem.Berkeley.EDU (Pete Goodeve) writes:

> Date: Sat, 22 Dec 2001 21:58:32 +0000 (UTC)
> Organization: University of California, Berkeley
>
> Stephen Isard  <S.IsardDeleteThis@ed.ac.uk> wrote:
> >
> >Well, you could do
> >
> >define echo();
> >	until dup(cucharin()) = termin then enduntil;
> >	.erase; ;;; don't include termin in the string
> >	consstring(stacklength())->str;
> >enddefine;
> >
>
> Umm.  That won't be very good if something is already on the stack
> when echo() is called, will it?
>
> After some more reading I came across this idiom, which -- although
> it still uses temp -- seems much the cleanest:
>
> define echo();
> 	lvars temp;
> 	''->str;
> 	until (cucharin()->>temp) = termin do
> 	str><consstring(temp, 1)->str;
> 	enduntil;
> enddefine;

There is a lovely construct invented by Steve Leach (I think) and
incorporated into Pop-11 some time around 1990 to deal with this sort of
case.

The two brackets

    "#|"  "|#"

can enclose an arbitrary Pop-11 expression which leaves items on the
stack.

The result of using the brackets is that the number of items ADDED to
the stack is also left on the stack.

E.g. See REF #|

which includes this example:

?               #| "a", "b", "c" |# =>
?               ** a b c 3

Compare
    vars list = [cat dog mouse elephant];

    explode(list) =>
    ** cat dog mouse elephant

but:

    #| explode(list) |#  =>
    ** cat dog mouse elephant 4

So you can use those brackets to inclose a loop.


  define echo() -> str;

    consstring(
    	#|
            until dup(cucharin()) == termin do enduntil,
                erase()
        |#) -> str

  enddefine;

The use of "erase" is to get rid of the termin left by dup.


Slightly more elegant and more obscure use "->" to do erase:

  define echo() -> str;

    consstring( #| until dup(cucharin()) == termin do enduntil -> |#) -> str

  enddefine;


Some people would prefer .consstring at the end.

Another example:

    define join(strings) -> string;

        ;;; take a list of strings and create one new string by
        ;;; concatenating them

        consstring(#| applist(strings, explode) |#) -> string;

    enddefine;

    join(['the' ' ' 'cat' ' ' 'sat']) =>
    ** the cat sat


The use of the stack instead of a temporary list or string to collect
items to put put in the final data-structure is very efficient. Using
good syntax helps to prevent obscure bugs caused by explicit stack
manipulation.

Aaron
====
Aaron Sloman, ( http://www.cs.bham.ac.uk/~axs/ )
School of Computer Science, The University of Birmingham, B15 2TT, UK
EMAIL A.Sloman AT cs.bham.ac.uk   (ReadATas@please !)
PAPERS: http://www.cs.bham.ac.uk/research/cogaff/ (And free book on Philosophy of AI)
FREE TOOLS: http://www.cs.bham.ac.uk/research/poplog/freepoplog.html