Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!yale!cmcl2!lanl!jlg From: jlg@lanl.gov (Jim Giles) Newsgroups: comp.society.futures Subject: Re: C's sins of commission (was: (pssst...fortran?)) Message-ID: <65027@lanl.gov> Date: 5 Oct 90 22:21:23 GMT References: <5116@uqcspe.cs.uq.oz.au> Organization: Los Alamos Natl Lab, Los Alamos, N.M. Lines: 117 From article <5116@uqcspe.cs.uq.oz.au>, by brendan@batserver.cs.uq.oz.au (Brendan Mahony): > [...] > Look the programmer is not the only person who has to cope with > the code the is written. The programmer may well be the person > who spends the least amount of time trying to understand the > stuff. The idea should be to produce code that is easily > comprehensible, rather than easily written. [...] All the more reason to use the conventional terminology and notation rather than force the user to conform to some purist's idea of what should be allowed by a programming language. My experience talking to large-scale users of such features is that they would be quite willing to spen considerable effort in the declaration of a random generator in order tha the _use_ of the thing retain conventional properties. For example, say I want a triangular probability distribution. The following two codes are examples of your style and mine: Yours: qran(z,seed) qran(x,seed) tri_dist = z-x Mine: tri_dist = ranf - ranf or: tri_dist = ranf() - ranf() Note, my experience is that the second of my forms (with the explicit denotation that ranf is a function call) is quite acceptable to users while your form is usually not. > [...] Included in that > criteria should be the ability to easily reason about the > behaviour of the code. [...] Given the rules of the language and a clear declaration of the fact that ranf() has side-effects, the forms I gave are susceptable to reasoning _identically_ well compared to your proposed form. The ability to reason about programs is impossible without knowledge of the language's rules - but it should be equally possible in any two well defined languages. > [...] I would agrue against global variables in > both procedures and functions on the grounds of > comprehensibility. [...] And I would argue in favor of global variables for the same reason. I find procedures with large and complicated calling sequences to be quite incomprehensible. Further, having to pass a data structure around through the calling sequence because it represents information which is shared by low-level routines I find appalling. For example, a simulator of a helicopter might have three routines (all deep in the call chain) which need the data structure describing the tail rotor: the power routine needs to know the state of the rotor to compute the power required to drive it, the structure routine needs to know the stresses the tail rotor is producing, and the aerodynamics routine needs to know how much torque the rotor is imparting into the air. Clearly, these functionalities are completely separate in the simulation - so you don't want to combine the three routines into one multi-purpose routine. But, you also don't want to have to force the rest of the program to carry around the tail rotor data which you don't want anything except the three low-level routines to be able to change or examine. The problem is, your data is 'helicopter shaped' but your program's procedure call chain is roughly tree shaped. By depriving the programmer the use of global data, you deprive him of the ability to partition his data into manageable small pieces which are imported only by those routines which actually use them. Now, of course, global data can be misused. I have seen some programs which deliberately import _all_ global variables into every routine. This means that you have no means of determining where a given data item might be used or changed. However, carefully used, global data can improve the comprehensibility of programs by isolating the data to those routines which actually need it and guaranteeing that all other routines will keep their electronic hands off. > [...] Procedures have the mediating factor that > their syntactic intent is to change program state. Side effects > in terms deny the syntactic intent of terms, which is to define > a value. I agree that this constraint makes the analysis of expressions much simpler. This is why I advocate explicit declaration of all side-effects that a function may produce - so that side-effect free expressions, (the majority) can be analysed in this simple way. Procedures which _have_ side-effects may make the program easier to analyse in other ways and at other levels than the expression level. I think that the user should be the one to decide which is most important to him. > [...] to understand the "meaning" of a term with side effects you > must break its evaluation down to a set of state changes, and > determine the sequence of this actions. If this activity is > required to make the code readable it should be reflected in the > code. Exactly. But this usually need not be such a burden as you seem to think. For random number generators for example, all that's needed is an attribute on the interface specification to the effect that it has side-effects. (The language I'm designing presently has the rather fanciful term 'fickle' for this property: a random number generator is a fickle function. Before we actually release the language to outside users we will probable switch to some more dignified or techie type of word. I don't know though - look through your thesaurus some time to see if you can find a better word - we couldn't.) In any case, a 'fickle' function must be regarded as having some internal state that causes its value to be different from call to call - even if the same arguments are sent (or no arguments at all in the case of random number functions). By the way, with your attitude toward side-effects, you must dislike C even more than I do. I thought I was the most anti-C person on the net. Maybe not. J. Giles