Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site mit-eddie.UUCP Path: utzoo!watmath!clyde!burl!mgnetp!ihnp4!mit-eddie!nessus From: nessus@mit-eddie.UUCP (Doug Alan) Newsgroups: net.lang Subject: Re: Gotos; tail-recursion Message-ID: <2042@mit-eddie.UUCP> Date: Tue, 5-Jun-84 03:15:58 EDT Article-I.D.: mit-eddi.2042 Posted: Tue Jun 5 03:15:58 1984 Date-Received: Wed, 6-Jun-84 06:21:52 EDT References: <1979@mit-eddie.UUCP> <1986@mit-eddie.UUCP> Organization: MIT, Cambridge, MA Lines: 136 From: gumby@mit-eddie.UUCP (David Vinayak Wallace): > Quite the contrary; throw (*throw) UNWINDS the stack, jumping > backwards. The two big features of throw are 1> that it unwinds > the stack (rather than just setting the PC) 2> That it has a > scope -- it's only applicable within the lexical (Scheme) or > dynamic (Lisp) scope of the corresponding catch. In my opinion, > the dynamic throw is almost as bad as ordinary GOTO -- you can't > clearly see the flow of control by just reading the code. It doesn't matter that the label comes before the jump. The jump is still in a forward direction. (I'm using "forward" to mean the direction that can't possibly cause you to loop.) The following two pieces of code do the same thing, even though one has the label at the beginning, and one at the end: (1) (print (*catch 'foo (let ((x 1)) (do-forever (print x) (setq x (1+ x)) (if (= x 10.) (*throw 'foo 3.1416)))))) (2) po: stream := stream$primary_output() x: int := 1 while true do stream$putl(po, int$unparse(x)) x := x + 1 if x = 10 then exit foo(3.1416) end end except when foo(y:real): stream$putl(po, real$unparse(y)) end In both the jump goes in the same direction. And who says that GOTOs only set the PC? If you have a language that allows GOTOs, and it also lets you GOTO out of a block that has it's own local variables, then it better do more than just setting the PC (unless the compiler has already accounted for this by preallocating the variables). Here part of the stack must be unwound. And, not only that, but who says that GOTOs can't have a scope? Lisp has GOs, but you can't GO out of the PROG statement. In some Pascals there are GOTOs, but you must declare a label, and you can't jump to that label if you are not in its scope. It seems to me that a GOTO is any statement that involves disrupting the natural flow of control of the program, and transfering control to someplace else that has been named. Unrestricted GOTOs, if used unrestrictedly are definitely bad things. But some types of GOTOs are definitely useful (like loop exits, etc.) We have to decide what restrictions on GOTOs make them palatable. I agree that dynamic throws are incredibly bad. I should have been more restrictive in my specification of good GOTOs. Not only are the labels for both THROW and CATCH computed at run-time, but even if they weren't, you still wouldn't always be able to tell just by looking a program where a THROW is THROWing to. ADA also has this problem with its error system. CLU does NOT have this problem with its EXIT or SIGNAL (for signalling errors) system. I haven't yet decided whether lexical THROWs are very good things. They're much better than dynamic THROWs, but you can still do some pretty weird things. > Unless you shun other structured iterative constructs (e.g. 'for' > in c) I don't see why to shun tail-recursion. It's not a > generalisation of goto; it's only useful in one place goto is. No, you're wrong. Tail recursive procedure calls are a generalization of GOTO. They are at least as powerful. You could implement GOTO with tail recursive procedure calls. Following is a simple translation of a BASIC program with GOTOs to a (Bad!) Lisp program with tail recursion: (1) 3 FO = 0 5 GOTO 10 7 END 10 PRINT "Hello" 20 FO = FO + 1 30 IF FO = 10 THEN 50 40 GOTO 10 50 GOTO 7 (2) (defun L3 () (setq fo 0) (L5)) (defun L5 () (L10)) (defun L7 () nil) (defun L10 () (print "Hello") (L20)) (defun L20 () (setq fo (1+ fo)) (L30)) (defun L30 () (if (= fo 10) (L50) (L40))) (defun L40 () (L10)) (defun L50 () (L7)) Of course, you could do the same with without tail recursion, but you would probably get discouraged pretty fast when you started getting stack overflows if your program ran for more than a few thousand steps. Without tail recursion, this would never discourage you, so if you might be tempted to do horrible things like this. I'm not saying that tail recursion is bad. Actually I think it is a good idea. But I think this problem is something to think about. > It's not clear I'd call Lisp an object-oriented language. The worst > confusion endengered with the Lisp class we're teachine at Stanford > right now is with object-oriented systems. My complaint with teaching > langages like Pascal is that all the features designed to make it easy > to program in actually get in the way of the studen't understanding of > the nature of programming, by presenting arbitrary distinctions between > "system" and "user" code (functions and operators, and ...), and by > presenting system-dependent abstractions (say , the io system in > Pascal). Whatever else its failings, at least lisp is more consistent > in its view of the world. Well I know that Smalltalk people use "object oriented" to mean that operations are run-time polymorphic on the type of the argument. But CLU people generally use object oriented to mean that something like that there are no second-class objects (though they've stopped using the term as much ever since Smalltalk people stole the term out from under them. . . .) In Pascal you can create integers, reals, and booleans, and return them to a higher scope than that in which they were created, but you can't do that with arrays, records, etc. In CLU, Lisp, and Smalltalk you can do this with an object of any type. I like this definition of "object oriented" better, because it's clear why it's name is is "object oriented", and I don't see what there is in the name that implies generics. Though I think generic operations are great, I think that this concept should be called something other than "object oriented". -- -Doug Alan mit-eddie!nessus Nessus@MIT-MC "What does 'I' mean"?