Imperative Notation

Nick Kallen nkallen@uclink4.berkeley.edu
Tue, 16 Feb 1999 02:27:03 -0800


> Ok, I read your examples and tried to see how far we can get
> using the things
> Clean has to offer.

Pascal: I'm sorry it took so long for me to respond to this message. I'll
add that I'm very grateful you took the time to code the combinators and
stuff to give us something concrete to discuss.

>      file_func1
>         = withFile "T.icl" FReadText (
>            writes "hello world" :\\
>            readline             =\\ \cs1 ->
>            readline             =\\ \cs2 ->
>            ret (cs1, cs2)
>            )

>      file_func2 =
>         openFile "T.icl" FReadText		=\ \f1 ->
>         openFile "T2.icl" FWriteText	=\ \f2 ->
>         et readline f1					=\
> \(f1, cs) ->
>         writes cs f2					=\ \f2 ->
>         close f1						:\
>         close f2 						:\
>         ret` Void

> files = file_func1 <|> file_func2

As for the above's merit.

In terms of brevity, it is quite clear that this last solution is better
than the explicit environment passing solution. One familiar with all of
these combinators could write pretty looking code.

However, it could easily be argued (and I'd be inclined to agree with those
arguing) that all of these combinators add complexity. It's easy to say:

=\ does this, =\\ does this, et does this, ret does this, ret` does that.
But learning all of these combinators such that one can quickly write
imperative code is no easy task. I still think a do notation is better at
accomplishing the following goal:

quickly writing clear, readable, understandable code.

Adding a do notation allows you to program at the level most natural for
imperatives: do this, do that, etc.

I'm going to translate your (modified) stuff back into my do notationy
thing.

>      file_func1
>         = withFile "T.icl" FReadText (
>            readline             =\\ \cs1 ->
>            readline             =\\ \cs2 ->
>            ret (cs1, cs2)
>            )

(I'm very fond of your withFile. This allows us to make anything the state.
One would preferably be able to generalize it to a polymorphic with).

file_func1 = do with (openFile "T.icl" FReadText)
	cs1 = readline
	cs2 = readline
	return (cs1, cs2)

Would we be able to do the following?:

return (readline, readline). Heh. I don't think so.

>      file_func2 =
>         openFile "T.icl" FReadText		=\ \f1 ->
>         openFile "T2.icl" FWriteText	=\ \f2 ->
>         et readline f1					=\
> \(f1, cs) ->
>         writes cs f2					=\ \f2 ->
>         close f1						:\
>         close f2 						:\
>         ret` Void

file_func2 = do
	f1 = openFile "T.icl" FReadText
	f2 = openFile "T2.icl" FWriteText
	cs = readline f1
	writes cs f2
	close f1
	close f2
	return Void

Now, both your and my code are (essentially) the same number of
lines/tokens/whatever. But I argue that mine is many fold easier to
understand and to write. Note how in your file_func2, you're forced to
explicitly use f1 as a continuation. Knowing when and where to write et, to
use =\ vs. =\\, ret vs. ret`, what returns two values (e.g., (f1, cs) vs.
cs)--that's all a huge mental burden, especially as imperatives get long and
complicated (as they presumably will in the so-called "real world").

Take a random Clean programmer, and I bet they could start programming in my
notation immediately, with less than 2 minutes of preparation, immediately
at a level of peak productivity. Ask this same programmer to use your
combinators, and I'm guessing it would take them a noticeable amount of time
to familiarize themselves with the combinators, and a significant amount of
time till they reach peak productivity. Even when they reach peak
productivity, typos and simple logical errors (like using =\\ rather than
=\) will result in really complex type errors and such that are hard to
debug. I assert that mine wont.

As I've said before it's probably easier to use the explicit CPS than all of
these combinators. However, I believe that my notation is significantly
simpler than both. I assert further that my code is as high level as you can
get about it.

Pascal, since you seem so willing to devote effort to this issue: as a
person who works with Clean (I'm assuming your job doesn't entail much IO in
Clean, but nonetheless), please analyze the statement:

"The above \"do\" notation would make me a more productive and happier human
being."

Pascal, again I want to say how much I personally appreciate the effort you
took toward writing those combinators.

-Nick