[Home] [Back to Message Index]

Global SchoolNet - Automated Message Archive

Re: LOGO-L> First-class procedures in Logo




Jean-Pierre L'Archeveque (jplarch@odyssee.net)
Sat, 4 Jan 97 13:49:24 -0400

Eric,

You recently wrote :

>Can you write procedures that return other procedures as their values
>in LOGO. I thought that define would do this for me but it seems
>that it will only create global procedures. I'm new to this and may
>be missing the boat but I wanted to try something like this:
>
>to gen.sq
> local "fun
> define :fun [[x] [:x * :x]]
> output :fun
>end
>
>to return a function that calculates the square of it's argument.
>This didn't work and I couldn't figure out what to try given the
>limited documentation I have access to. Is there a way to return a
>function in the same way that you do in Scheme when you write a
>function that returns a lambda expression?
>
>Thanks, EK

You don't mention which version of Logo you are using.
Keep in mind that the following applies to UCB Logo 3.4 (which I =
recently downloaded).
I know that DEFINE does not exist in every Logo dialects.

>This didn't work

Here is why :

1=B0 DEFINE expects a word as it's first argument
(even the empty word will do! but ... see below)
So you must add a line:

make "fun "fun.name (N.B. The procedure created will be named =
"fun.name)

2=B0 Since you want to create a logo FUNCTION (not a command), your =
next line should read:

define :fun [[x] [op :x * :x]]

Your procedure gen.sq might be rewritten like this

to gen.sq
local "fun
make "fun "fun.name
define :fun [[x] [op :x * :x]]
output :fun
end

3=B0 Since gen.sq will output the NAME of the created procedure,
any of the following should now work as you expect.

a) print run list gen.sq 5
b) print run se gen.sq 5
c) print run fput gen.sq [5]
d) print apply gen.sq [5]

N.B. The first three lines won't work when gen.sq outputs an empty =
word.
(I am sure Brian Harvey, author of UCB Logo, could explain =
this).

>Can you write procedures that return other procedures as their values
>in LOGO. I thought that define would do this for me ...

DEFINE is a command and does not return anything.

> ...but it seems that it will only create global procedures.

It's true that you don't have local procedures (like you have local =
variables),
but you can emulate that

1=B0 by making sure you always use an unused name for the created =
procedure.
2=B0 by explicitly erasing the created procedure when you don't =
need it anymore.

To generate an unused name for a procedure, you could use :

to new.proc.name
op gen.proc.name char 32
end

to gen.proc.name :base.name
if not procedurep :base.name [op :base.name]
op gen.proc.name word :base.name char 32
end

Then your procedure might look like this

to gen.sq
local "proc.name
make "proc.name gen.proc.name
define :proc.name [[x] [op :x * :x]]
op :proc.name
end

A typical use of gen.sq would be :

make "temp gen.sq
make "result apply :temp [5]
ER :temp
...

You might even consider a pair of tools:

to apply.command :command.text :arglist
local [name]
make "name new.proc.name
define :name :command.text
apply :name :arglist
er :name
end

to apply.function :function.text :arglist
local [name result]
make "name new.proc.name
define :name :function.text
make "result apply :name :arglist
er :name
op :result
end

and write:

print apply.function [[x] [op :x * :x ]] [5]
or:
apply.command [[x] [print :x * :x ]] [5]

Of course, if you need the created procedure more than once,
it's more efficient to create it only once, use it with APPLY
and then ERASE it, as outlined above.

Hope this helps.

N.B. You should love the tools introduced in the Logo world by Brian =
Harvey.
They are included in the UCB Logo package.
You will find them in his book Computer Science Logo Style, Vol 3

Jean-Pierre L'Archeveque
---------------------------------------------------------------
Please post messages to the Logo forum to logo-l@gsn.org. Mail
questions about the list administration to logofdn@gsn.org. To
unsubscribe send unsubscribe logo-l to majordomo@gsn.org.