As I already explained, I’ve invented and implemented a simple functional language (PYFL) with a few interesting twists. Including a promising but simple approach to input.

The basic language itself is pretty standard, except that it uses infix operators and conventional mathematical notation for function calling; e.g. f(h,a+2*y). It also has a wide range of variable binding operators; as in the program given at the end of this post

VBOs are great but the real elephant in the FP room is I/O. I have a few ideas.

Haskell uses the seriously complex machinery of monads to do I/O, supposedly without side effects (I don’t accept this). And you end up writing stuff like

which to me looks like C. There must be a more functional approach.

I started from the PyLucid approach, that the output of a program is its value (as an expression) and its input is the value of a special variable input. Simple enough.

The problem with adopting this is that pyLucid has streams and PYFL doesn’t. Infinite lists could serve as a substitute but PYFL has only finite lists (to avoid the complications of list closures)

But there is no harm in having an input variable and this gives us a simple arrangement: the input becomes the value of input, and the corresponding value of the program is the corresponding output. Thus the expression

input*input

is a program to compute the square of its input (note that both occurrences of input denote the same value – no side effects, this program is equivalent to input**2).

What if we do want two inputs, and output their product? If one input variable is kosher, we can have two, input and input2. Our program is input*input2.

Generalizing, we could have inputn for every number n. Even better, a function input(n) of one number argument. When the computation (which is demand driven) needs the value of, say, input(3), it could prompt for it. In this  simplest form the scheme is impractical because in general there is no guarantee that these inputs will be demanded in numerical order; the computation may need input(4) before input(3).

The solution (following Lucid) is to demand the inputs in order and cache them, so they will be available when the computation needs them.

Input prompting

PYFL goes one better. It has an input function whose argument can be an arbitrary string (not necessarily a numeral). This string is used as a prompt. Thus a program to compute the roots of a quadratic equation could be (and in PYFL is)

valof
a = input(‘coefficient of x squared’);
b = input(‘coefficient of x’);
c = input(‘constant coefficient’)
rdisc = sqrt(b*b-4*a*c);
root1 = (-b + rdisc)/(2*a);
root2 = (-b – rdisc)/(2*a);
result = [% root1, root2 %];
end

As it happens the computation will need the value of b before that of a. If this is a problem, we can write the definition of  root1 as

root1 =  (1/(2*a))*(-b + rdisc);

(later I’ll explain a more systematic approach). Then the demand for root generates a demand for root1 which generates a demand for 1/(2*a) and finally a demand for a. Demands for b and c follow shortly, in that order.

Input values are cached in a dictionary using the prompt itself as a key. Thus the implementation won’t ask you again for the coefficient of x squared.

This works well if there is a small finite set of inputs but what if, say, we wanted to sum the values of twenty inputs?

The answer is to generate prompts and embed the a call to the input function in a VBO that runs over the required range. For example

sumfor i in range(1,20) all
end

where str converts numbers to strings.

What if the input is being produced by another program? Why would we print the prompts? Because the program can read them digitally, and produce output as required. In other words the producer program is feeding our consumer program by producing its output on demand. It receives a prompt and computes or looks up the corresponding output.

We can save a lot of trouble if the producer knows ahead of time the order in which the input items will be required. Then we can eliminate the prompting dialogue.

The input scheme is not only conceptually simple (none of those pesky monads) but is trivial to implement – about a dozen lines of Python.

Now for output. The idea is … wait, take a look at the word count … this is already too long, the output story will have to wait till next time. Prompt me.

Here’s the promised program

valof
subsets(s,i) =  // the set of all i-element subsets of set s
if i==0 then {{}}
i==1 then collectfor x in s all {% x %} end
else
unionfor x in s all
valof
sminusx = s – {% x %};           //  {% x %} is singleton x
withoutx = subsets(sminusx,i);  // subsets without x
withx = collectfor u in subsets(sminusx,i-1) all //those  with x
{% x %} ++ u
end;
result = withx ++ withoutx;    // disjoint union
end
end
fi;
result = subsets({tom dick harry chris pat},3);
end

which computes all the three element subsets of the set {tom,dick,harry,chris,pat} (PYFL has proper sets). I am a retired Professor in Computer Science at UVic.
This entry was posted in Uncategorized. Bookmark the permalink.

1. Dave says:
2. Kate says: