[comp.lang.forth] Forth and Functional Languages

orr@cs.glasgow.ac.uk (Fraser Orr) (09/12/88)

In article <8809092121.AA09902@jade.berkeley.edu> Forth Interest Group International List <FIGI-L%SCFVM.bitnet@jade.berkeley.edu> writes:
>Fraser Orr writes:
	[Stuff that I believe justifies the following assertion
	 deleted]
>>Forth bears absolutely no resemblance to any functional programming
>>language I know, (appartfrom the fact that the both run on a computer of
>>course :^>).
>
>First of all, I don't think the original poster was claiming that the
>paper backed up FORTH as a wonderful programming language, but rather
>that it singled out modularization as the greatest good; the fact that
>FORTH makes it easy to completely modularize code then implies that
>FORTH is a ``good'' language *in this regard*.
>
>Obviously, however, you do not agree that FORTH allows easy and
>complete modularization.  I think we need a definition of modularization.
>I suspect you are in fact referring to language facilities directly
>aimed at building modules.  If so, you are correct, plain FORTH has
>none.  But even the computer scientists agree that modularization is
>something that happens in the programmer's head, not in the language.
>So to say that modularization is not available in FORTH is a misstatement.

Yes, you've got me there. I'm sorry, but that wasn't really the intent
of what I was saying. Clearly modularisation is possible in all
languages (even down to the ubiquitous 68000 assembler), the question
I was adressing was the support the progrmming language provided for
modularisation. Now let me restate my point, Forth has very little support
for the programmer's concept of modulariation (with the above proviso)

>Further, I remember reading of at least one example of adding MODULA
>style modules to FORTH ``in a few simple screens of definitions.''
>(Before you object that this is not part of the standard, keep in mind
>that most functional programming languages start out with a very simple
>(but powerful) core to which quite a bit of code must be added before
>you have an adequate *programming* environment.  Sound familiar?)

I'm no expert on all the functional languages in extant. Those that I
do know of though do need this package of extra stuff. The point though
is that this packet of extra stuff is STANDARDISED. It comes with all
releases of the language, so everybody has them avaliable, they are not
added and rebuilt by every miranda programmer. Moreover many of the things
we have been discussing in this group come as part of the language itself
(as it should be), things like modularisation and glue, they are not bits
stuck on as an afterthought, but are fully integrated into the language.

>But even (or especially) *without* MODULA style modules FORTH provides
>a good environment for modularization because it allows the problem
>to be decomposed in a way that fits the *problem*, not the programming
>language.  (Of course, some traditional languages are better at allowing
>this same kind of decomposition than others.)  A program design book
>I was reading recently (yes, Fraser, I found a generic one) maintains
>that the proper way to decompose a program is to design data structures
>in terms of the operations that may be performed on them (including
>transformations between data structures).  FORTH is excellent for this
>kind of decomposition, better than any traditional language I know.
>(C++ and SmallTalk may be as good; I don't know them.)

Come on David. If you're going to make statments like this it would
be helpful if you could give your reasons for believing so. I cannot
even imagine why you believe this because I see no way in which forth
is better at this sort of this that just about any other language I
know (in fact I can see no way in which forth is not worse at this
sort of thing than just about any language I know, my justification?
Hidden parameter lists - thus it is dificult to see the data flowing,
lack of type checking thus loosing all the benifits of having the
compiler check out you are using data properly.)

You reminded me that I had promised someone to post the name of a good
generic program design book, I forgot who it was so I'll post it here,
I would recomend -
"Software Enginerring - A Practitioner's Approach"
by Roger PressMan (McGraw-Hill 2nd Ed)

You go on to discuss some of the things I said were avaliable in
Functional languages but not in Forth. I've missed out the things
we agree on to a large extent.

>  Higher order functions: are functions that operate on other
>    functions as data.  FORTH can do this in several ways, since a
>    function can be represented by its address.  Agreed, this is not
>    as elegant in practice as true functional programming,

As I said above, you can also do this with 68000 assembler, the
improtant thing is the notational convenience. In functional languages
(the ones I know that is) the higher ordered-ness is not stated
explicitly, but implied from the context. I'm not convinced this is good
because there are a lot of errors that could result from this (most
of which will be picked up by the type system), I don't know if
I would prefer a seperate notation for partially applied functions
The big win in functional languages (fl from now on) is that they
provide this sort of facility with type checking.

>  FORTH glue bad because it is untyped:  Since when have functional
>    program glues been typed?  I didn't think that type checking was
>    part of the fundamental design.  

All the fl that I know have type checking as one of their central
features. I've only seen Bakus' FP from afar, and what I saw, I don;t
want to see any more. I'm interested in the new functional languages
that are being designed now, and have been in the near past. And in
answer to your implied question, yes this type checking is done at
compile time (or pre-run time in the Miranda we have, which is interp)

>  Complex data structures:  FORTH can pass data structures of
>    arbitrary complexity; this is one of its strengths.  Any data
>    structure is represented by the address of its root.

Again you can do this in assembler, notation is the important thing.
There is no standard forth notation for records (that I know of anyway).

>  Explicitness:  Functional programs may be explicit about what
>    functions are getting what arguments, but you still have to
>    visualize the actual data being handed around to *really* see what
>    is going on.  If I see  f(g(h(z))) I have to visualize the result

As I've said earlier I would be in favour of a pipeline notation
as an alternative to function composition.

That is ...


h (h-list) | g (g-list) | f(f-list) is equivilent to
f(g(h(h-list),g-list)f-list)

>  Type security:  Again, how does functional programming provide
>    type security?  (That's not a challenge, that's an honest
>    question.)

See above. FLs are the most type secure langusges I've ever used.

>  FORTH as a functional programming language:  As I understand it,
>    the basic characteristic of a functional programming language
>    is that a function always has the same result when given the
>    same input values, regardless of the state of its environment.
>    Many many FORTH words have this characteristic.  A number do not,
>    and many of these are critical to the functioning of the FORTH
>    system.  It is this latter that makes FORTH appear so un-functional.
>    Good FORTH programs minimize and restrict these state-changing words.
>    Consider how few variables good FORTH programs have relative to
>    traditional programs and FORTH may start to seem more functional.

If your saying that people should write in a functional style then great,
I agree. All I'm saying is that your programming language should to as
large an extent as is possible back up your programming style. FLs back up
a functional style, forth in my opinion backs up a very low level style
(by the falure of the language to abstract away from implementation details)
I can't justify this without a few years of research, so I'll have to leave
it as a gut reaction, that I'm sure you'll all agree with :^)

>FORTH programs can be made more functional by reducing non-local variable
>use.  Higher order functions and lazy evaluation of some functions can
>be introduced if sufficiently desirable.  (I'll have to think about
>that some.)  FORTH runs efficiently on current hardware.  Until
>functional programming languages come of age, I'll stick to FORTH.
>(But I'll try to investigate Miranda.)

Yes, this is all true. You can make any program more functional by
applying these rules, regardless of their programming language.

Functional programming is educational in that it challenges you to
program in other languages in a better manner. I agree with you that
FLs are too slow for all practical intents just now (and I don't
and wouldn't use one for my work). It is possible to put many functional
features into languages that can be used practically. Now if forth had
a pre-processor ... (Yawn, YAWN, Yawwwww zzzZZZZZ !    :^)

>-- R. David Murray    (DAVID@PENNDRLS.BITNET, DAVID@PENNDRLS.UPENN.EDU)

You other forthers might think this is an inappropriate discussion
for this group, but for the reasons outlines above I think it is benificial
since by looking at the strengths and weaknesses of other langauges
(and I freely accept that Miranda has both strengths and weaknesses)
we all might learn something that we can take back and apply to our
own style of programming. I would recomend that everybody learned
at least simple functional programming, and I certify that you will
be a much better programmer for it.

Regards,

===Fraser

oster@dewey.soe.berkeley.edu (David Phillip Oster) (09/15/88)

We've been talking about "very high level languages", and "functional 
programming languages" and "languages with linguistic support for 
modularity". I prefer to lump them all together as "languages inspiring 
superior programming."

Many forth programmers have never seen a "language inspiring superior 
programming" better than Pascal, C, or Fortran.

I'm going to be using the phrase "language inspiring superior programming"
a lot in this article, so I'm just going to abbreviate it LISP from here on
out.

In LISP, every data object (the equivalent of a Forth address) is tagged 
with a type. Operations such as "+" check the tag type
of their operands and do the appropriate thing without any human 
intervention. 

In Pascal, You get error messages if you apply an operator to inappropriate
types. In Forth you just get garbage results. In LISP the
language will do the operation if it can. If it can't you'll get an error.
(An error is a special kind of object, with special flow control properties,
similar to resetting the return stack, except in LISP you can specify
that certain clean-up operations, such as closing open files, will happen
automatically if anybody, even the operating system, generates an error during
the program.)

In LISP you can add new data types and have them automatically take advantage
of all the existing capabilities. For example, suppose you define a new
kind of number, say complex number, and you want to use the convenient
notation of (a + b) * c where "a" might be a floating point number, "b"
an integer, and "c" a complex.

In Pascal you can't use "+" to add complex numbers. You can
write your own function to add complex numbers, but you loose access to
the outer interpreter of Pascal's knowledge that most human beings mean
"a b + c *" when they write "(a + b) * c".

In Forth, you can, but you have to use a special version of "+" that lives
in a different vocabulary from the integer "+" and you must explictly
tell Forth to switch vocabularies. Since forth does not automatically
keep track of the types of operands and automatically insert type
coercion operators, you'd have to write something like:

A @ FLOATVOC B @ INT->FLOAT + FLOAT->COMPLEX COMPLEXVOC C @ *

much more cumbersome and error prone. (Note that I have to explicitly
switch vocabularies to get floating "@", and again to get complex "@".

If you don't have special hardware to do the tag analysis, doing the tag
will slow the system down. Therefore many very high level languages have
a compiler (the equivalent of the Forth outer interpreter) that, tries
to determine the types of the operand. If it can it produces threaded
code that directly performs the reuired operation, so it does the tag
analysis in zero time.

For example, if you multiply "65536 * 65536 * 65536" you'll get the wrong
answer in Forth or Pascal, because that expression requires a 48 bit integer,
and neither language supports the automatic overflow of integer arithmetic
into variable sized big numbers, each as big as it needs to be. Better LISP
systems do this. On the otherhand, if you are using the "i" of a "FOR"
loop, and you write "i * i", the compiler can deduce, based on the upper
bound of the for loop, that that expression will never overflow a 16-bit
integer, and generate simple, fast code to evaluate it.

Pascal is type strict: the compiler must be able to tell, strictly from
	by your inclusion of extra type declarations, the type assignment
	of every object in every expression. You can't extend the domain
	of the built in operators like "+" to handle new types.

LISP is type safe: if the compiler doesn't know the types, they'll
	have to be checked at run time. 
	You can extend the domain of the built in operators like "+" to 
	handle new types. You can set up the system to detect and do 
	something reasonable on overflow.
	Often type checks can be made at compile time, so the run time
	cost is zero.

Forh is chaotic: if the programmer accidently applies an operator to
	inappropriate arguments, he is screwed. He has to find it himself,
	the compiler and the run-time system aren't going to tell him.


--- David Phillip Oster            --When you asked me to live in sin with you
Arpa: oster@dewey.soe.berkeley.edu --I didn't know you meant sloth.
Uucp: {uwvax,decvax,ihnp4}!ucbvax!oster%dewey.soe.berkeley.edu

jax@well.UUCP (Jack J. Woehr) (09/16/88)

in article 2,347,968 orr@cowdor writes:

>blah blah blah, etc.

	No, really, Fraser, your postings are very interesting, but
not enough so that I am going to burden the net by quoting them too
often! :-)

	Type checking? Forth does it. It is type STACK or it doesn't
exist!

	Really, what ever happened to the concept of MLL's? Why does
everyone try to prove that Forth is a lousy HLL? C is a lousy delcarative
language for that matter. Prolog is a lousy procedural language.

	Forth is MLL for them what need an environment that allows
them to roll their own, to Go Where No Man Has Gone Before.

*************
jax@well		Orr, Orr ... where have I heard that before?
jax@chariot		Warnier Orr diagrams? Any relation?
JAX on GEnie

ritchie@hpldola.HP.COM (Dave Ritchie) (09/18/88)

>
>For example, if you multiply "65536 * 65536 * 65536" you'll get the wrong
>answer in Forth or Pascal, because that expression requires a 48 bit integer,
>and neither language supports the automatic overflow of integer arithmetic
>

  I don't think so. try 51 bits + sign if in signed representation.
					Dave 

ritchie@hpldola.HP.COM (Dave Ritchie) (09/19/88)

>/ hpldola:comp.lang.forth / ritchie@hpldola.HP.COM (Dave Ritchie) / 11:30 pm  Sep 17, 1988 /
>>
>>For example, if you multiply "65536 * 65536 * 65536" you'll get the wrong
>>answer in Forth or Pascal, because that expression requires a 48 bit integer,
>>and neither language supports the automatic overflow of integer arithmetic
>>
>
>  I don't think so. try 51 bits + sign if in signed representation.
>					Dave 

  Jeez, I shouldn't respond to notes late at night.... 49 bits (an 1 bit 
followed by 48 zero bits) + sign.
					Dave 

orr@cs.glasgow.ac.uk (Fraser Orr) (09/21/88)

In article <7122@well.UUCP> jax@well.UUCP (Jack J. Woehr) writes:
>	Really, what ever happened to the concept of MLL's? Why does
>everyone try to prove that Forth is a lousy HLL? C is a lousy delcarative
>language for that matter. Prolog is a lousy procedural language.
>
There are two possibilities for what MLL stands for: Medium level language;
Machine level language. The latter I agree is a fair catagorisation of forth.
In fact that is what I've been saying all along. To say though that this is 
a great thing is not very sensible. It is clear that the purpose of a
programming language is to make the machine easier to use without loosing
any machine function (which can most certainly be done in practice)

I agree that forth is a more powerful assembler than most, but it is still
an assembler. I don't want to use this assembler any more than any other,
(although I might like to use a compiler that had the advantage of producing
this more powerful machine model.)

Regards,
===Fraser

scowl@psu-cs.UUCP (Scott W. Larson) (09/24/88)

In article <1643@crete.cs.glasgow.ac.uk> orr@cs.glasgow.ac.uk (Fraser Orr) writes:
>I agree that forth is a more powerful assembler than most, but it is still
>an assembler. I don't want to use this assembler any more than any other,
>(although I might like to use a compiler that had the advantage of producing
>this more powerful machine model.)

I'd like to see some justification for this comment! Why do you
consider Forth to be just an assembler? Do you consider it to be
an assembler because it is flexible, extensible, and easy to 
understand while compilers are rigid, complex, powerful monsters
that produce highly complex code from complex high-level code?
While Forth might be on the very lowest end of high-level lan-
guages, writing Forth is far closer to writing in Pascal than
writing 68000 assembler code! I suspect you're confusing the
two because people who write in Forth, like those who write
assembly code, don't view the compiler (or assembler) nor the
compiled (assembled) code as hopelessly complex and mysterious.

olorin@juniper.uucp (David Weinstein) (09/25/88)

In article <1643@crete.cs.glasgow.ac.uk> orr@cs.glasgow.ac.uk (Fraser Orr) writes:
>There are two possibilities for what MLL stands for: Medium level language;
>Machine level language. The latter I agree is a fair catagorisation of forth.
>In fact that is what I've been saying all along. To say though that this is 
>a great thing is not very sensible. It is clear that the purpose of a
>programming language is to make the machine easier to use without loosing
>any machine function (which can most certainly be done in practice)

No. Or I'll make it a challenge. Pick a high-level language, and a common CPU
for which there are programmers working in assembly regularly. Now, chose a
problem. While the HLL programmer may finish first, a good assembly language
programmer will produce *much* more efficient code. Furthermore, conventional
languages can't work in many areas (do you want to explain why you need 4 more
inches of space on the board to hold all the libraries your compiler linked in
along the way... :-)

The attitude, "If the program written in an HLL isn't fast enough then my
compiler isn't good enough, and if my compiler is good enough but it's still
too slow I'll buy a new machine", (which is a paraphrasing of a comment I
found on comp.lang.misc a week or so ago) is one of the things that disturbs
me most about CS departments (or at least the ones I've been in a position to
observe). Quite simply...you can't really do that in the real world, with
finite resources. Upper management in many cases will find your programming
time a more reasonable expense then replacing the computer you just got with
a faster one (and compiler revisions are infrequent at best...and remove old
bugs simply to replace them with a host of new bugs). I shudder when I think
the CS students who *don't* work in the real world while pursuing a degree, 
and face a dreadful shock when they get out of the ivory tower. 




-- 
Dave Weinstein
Internet: olorin@walt.cc.utexas.edu
UUCP: {ames,utah-cs,uunet}!ut-sally!ut-emx!{walt.cc.utexas.edu,juniper}!olorin
GEnie: DHWEINSTEIN

orr@cs.glasgow.ac.uk (Fraser Orr) (09/29/88)

In article <4889@juniper.uucp> olorin@juniper.UUCP (David Weinstein) writes:
>
>In article <1643@crete.cs.glasgow.ac.uk> orr@cs.glasgow.ac.uk (Fraser Orr) writes:
>No. Or I'll make it a challenge. Pick a high-level language, and a common CPU
>for which there are programmers working in assembly regularly. Now, chose a
>problem. While the HLL programmer may finish first, a good assembly language
>programmer will produce *much* more efficient code. Furthermore, conventional
>languages can't work in many areas (do you want to explain why you need 4 more
>inches of space on the board to hold all the libraries your compiler linked in
>along the way... :-)

*Much* more efficient?  This seems rather a strong statment.  Although
when programming in MLLs you can problably produce *somewhat* more
efficient to say only this is to present a very narrow perspective.
Firstly in HLLs you program closer to the problem area, so more thought
can go into things like algorithims and program layout.  This can in
some cases even lead to *much* more efficient HLL programs (because you
chose a better algorithim - I seem to remember mentioning this a while
ago though).  Yes I know that anything you can do in an HLL you can do
in an MLL, but in MLL programming (in my experience of it anyway) you
usually can't see the wood for the trees.  Of course a far more
important argument is that generally you can produce HLLs with far fewer
bugs (again because your program is closer to the problem domain), and
in my humble opinion a program that gives the right answer after an
hour, is much better than one that crashes after five minutes.
Furthermore a good optimising compiler can produce very good code
indeed.  Although it can't make some of the problem oriented
optimisations that can be made in an MLL (and often also in an HLL) they
can make other ones that would be tedious in the extreme for a human to
do (an example that immediately springs to mind is efficient register
usage.)

As to board space, don't blame me if you've got a rotten linker!  :^> I
guess the problem with the linker is that it was written in an MLL and
although it is faster than lightening, it was too dificult to put in
features like selective loading...  :^>

>The attitude, "If the program written in an HLL isn't fast enough then my
>compiler isn't good enough, and if my compiler is good enough but it's still
>too slow I'll buy a new machine", (which is a paraphrasing of a comment I
>found on comp.lang.misc a week or so ago) is one of the things that disturbs
>me most about CS departments (or at least the ones I've been in a position to
>observe). Quite simply...you can't really do that in the real world, with

Hmmh, you've got a point.  I take the acedemic view you outline above
(surprise, surprise!) and I think that this is a reasonable veiw for an
academic to take, since academic's job is to look to the future (when
there most certainly will be bigger faster and better computers about.)
But I accept that this cannot be the veiw taken in the "real" world.  If
you remember earlier I was saying that my favorite language was Miranda,
but that I didn't use it in my job, because it was too slow.  (That of
course doesn't mean that Miranda is no good, because there will come a
time when the computers are big and powerful enough to run Miranda)

>observe). Quite simply...you can't really do that in the real world, with
>finite resources. Upper management in many cases will find your programming
>time a more reasonable expense then replacing the computer you just got with
>a faster one (and compiler revisions are infrequent at best...and remove old
>bugs simply to replace them with a host of new bugs). I shudder when I think

I think that you have a cheek to talk about bugs!:^) You are advocating
a style of programmning that produces far more bugs than I have problems
with compilers.  Compiler bugs I agree are a real pain, but they can be
documented and got round.  Anyway, what are you suggesting, write your
compiler in MLL, and put in even more bugs?:^>

>bugs simply to replace them with a host of new bugs). I shudder when I think
>the CS students who *don't* work in the real world while pursuing a degree, 
>and face a dreadful shock when they get out of the ivory tower. 

Again you have a point, I think that a lot more practical stuff in CS
courses would be of great benefit.  But also of great benefit is to
expose students to "pure" programming techniques so that they know
whereabouts they are making compromises for the sake of efficiency.

>Dave Weinstein

Regards,
===Fraser