[Date Prev] [Date Next] [Thread Prev] [Thread Next] Date Index Thread Index Search archive:
Date:Mon, 11 Oct 2004 09:46:09 +0000 (UTC) 
Subject:Re: string library question (fwd) 
From:A . Sloman 
Volume-ID: 

Brent,

Thanks for the message about the file hierarchy standard, which I'll
check out later here:
	 http://www.pathname.com/fhs


> I'm trying to write native pop11 implementations of the shootout tests
> (http://alioth.debian.org).  Unfortunately, I'm completely flummoxed by
> the simple effort of converting input parameters into numbers.
>
> For example, here's an attempt at writing a simple Ackermann's
> function:
> ==================================================
> ;;; $Id: ackermann.poplisp,v 1.1 2003/06/25 09:57:13 dada Exp $
>
> define fast_ack (m, n) -> result;
>     if m == 0 then
>        n + 1 -> result
>     elseif n == 0 then
>        fast_ack(m - 1, 1) -> result
>     else
>        fast_ack(m - 1, fast_ack(m, n - 1)) -> result
>     endif
> enddefine;

One problem with this is that pop11 does not do tail recursion
optimisation. I forget all the reasons for this, but some have to do
with the availability of the dlocal constract.

Also because (unless the procedure name is defined as a constant
identifier), the definition of a procedure can change while the
procedure is running, e.g. in a separate pop11 lightweight process
running concurrently. (See HELP PROCESS, REF PROCESS).

So the ackermann function can get very deep into recursion. That
means you'll have to increase both pop_callstack_lim (explained
in REF PROCEDURE) and popmemlim (explained in REF SYSTEM).

So (depending on the amount of memory and swap space on your machine)
try something like this (the numbers are just examples, not
recommendations):

	100 * pop_callstack_lim  -> pop_callstack_lim ;
	20 * popmemlim -> popmemlim ;

(NB both variables refer to the number of words, not bytes. So,
for example, on a DEC Alpha divide available memory in bytes
by 8 to get the memory size in words, and on most others divide
by 4.)

It is possible (though tricky sometimes) to implement your own tail
recursion optimisation for particular procedures using 'chain'
(see HELP CHAIN).

E.g. a recursive listlength procedure (length is already in the system):

define len(list);
	if null(list) then 0
	else
		;;; put 1 and the tail on the stack, then chain to a procedure
		;;; that runs len, then runs +
		1, tl(list), chain(procedure(); len(); +  endprocedure)
	endif
enddefine;

chain returns from its caller, then runs its argument.

len([]) =>
** 0

len([a b c]) =>
** 3

It's ugly but it stops the stack from growing. Note that
the 'procedure .... endprocedure' syntax corresponds to the
use of 'lambda' in lisp to construct anonymous procedures.

Alternative, but equivalent version:

define len(list);
	if null(list) then 0
	else
		;;; put the tail on the stack, then chain to a procedure
		;;; that runs len, then runs + 1
		tl(list), chain(procedure(); len(); + 1  endprocedure)
	endif
enddefine;

(Note '+' has a dual role, different in '+1' and '+ 1'. In the
first case it is a unary operator. In the latter it is a binary
operator. Likewise '-1' and '- 1'.)


I have not tried to work out what you'd have to do with the ackermann
function. It would require a second call of chain inside the
procedure ... endprocedure expression.

This is the source of your main problem.

> define get_args() -> result;
>     if null(pop11::poparglist) then
>        1 -> result
>     else
>        strnumber( hd(pop11::poparglist) ) -> result
>     endif
> enddefine;

I think you must have got confused about the requirement for the
'pop11::' package prefix in poplog lisp. This is not needed in
pop11.

I.e. just use 'poparglist', not 'pop11::poparglist'.

The latter will try to cons the value of "pop11" (an undefined
identifier) onto the list poparglist, and consequently, null will always
return false.

Likewise hd(pop11::poparglist) will not return what you expect:

	hd(pop11::poparglist) =>
	;;; DECLARING VARIABLE pop11
	;;; IN FILE message
	;;; LINE 303
	** <undef pop11>

It returns an undef record (See REF IDENT, REF DATA ). Then
strnumber complains that it has not been given a string
as argument, because it is given an undef record

	strnumber(hd(pop11::poparglist)) =>
    ;;; MISHAP - STRING NEEDED
    ;;; INVOLVING:  <undef pop11>
    ;;; FILE     :  message   LINE NUMBER:  339
	;;; DOING    :  strnumber runproc


What I think you wanted is something like this:

define get_args() -> result;
    if null(poparglist) then
       1 -> result
    else
       strnumber( hd(poparglist) ) -> result
    endif
enddefine;

> vars n;
> get_args() -> n;
>
> format_print('Ack(3,~D): ~D\n', [^n ^(fast_ack(3, n))]);

I have not checked that. I normally use printf, and prnum rather than
format_print, but that's just a question of what I am familiar with.

> ===============================================
>
> Now, the thing that's causing me so much trouble is the use of the
> "strnumber" procedure, which is apparently defined in a "string"
> library according to the HELP system.

I hope it's clear that there's nothing wrong with your use
of strnumber: the problem lies elsewhere.

> But if I try to compile the procedures, I get errors:
>
> brent@hopper:/opt/shootout/shootout/bench/ackermann$ poplog pop11
> ackermann.poplog 2
> Sussex Poplog Version 15.53
> ;;; DECLARING VARIABLE pop11

That's your first clue that something is wrong.

> ;;; IN FILE /opt/shootout/shootout/bench/ackermann/ackermann.poplog
> ;;; LINE 18
>
> ;;; MISHAP - STRING NEEDED
> ;;; INVOLVING:  <undef pop11>

As above.

> ;;; FILE     :  /opt/shootout/shootout/bench/ackermann/ackermann.poplog
> ;;;       LINE NUMBER:  27
> ;;; DOING    :  strnumber get_args trycompile
> brent@hopper:/opt/shootout/shootout/bench/ackermann$
>
> Apparently I need to tell Poplog to include the "string" library.

I have never heard of this string library. Where did you get the
information? The procedure strnumber is built in to pop11 as one
of the core procedures, defined in

	$popsrc/item.p

> I've grepped through the Poplog sources to see if anything else in the
> system uses the "string" library, but find nothing.  If I search for a
> library called "string.p" or "string.ph" I find nothing.
>
> I also tried searching for "strings.p" and "strings.ph" to no avail.
>
> I am really new with Poplog, so I'm surely missing some trivial aspect
> of this, but I'm a bit lost.  Can anyone provide some clues?

Some misleading piece of documentation has led you up the garden path.

If you can say where it was, perhaps it can be changed. Something
in the Pop11 Primer perhaps?

Aaron