| PLEX86 | ||
IBM 610 workstation computer 3392Have you tried to read the whole paper? Most of the audience started out with similar unfamiliarity. IBM 610 workstation computer 3395 David Scheidt Unfortunately, in recent years the cheap extra speed and storage has resulted in (IMHO) considerable bloat, not increased... OK. The von Neumann computer (architecture) is the normal one we are all familiar with. Alternatives include weird things like dataflow and reduction machines, which have been built, but really only as research projects. The distinguishing feature of the von Neumann architecture is that the CPU is separate from the memory, and the path between the two forms a bottleneck, canonically only one word wide (caching is an attempt to overcome the worst effects of this, but doesn't change the fundamentals). The canonical instruction set for von Neumann machines is based on moving values between memory and processor - load and store instructions, so programming, initially in machine code and buttembler, does a lot of that. The development of high-level languages did not change that, it modelleled itself on that style of programming, hence the ubiquity of buttignment statements. IBM 610 workstation computer 3393 This is a difficult topic to teach. The serialisation that is implicit in the "von Neumann" model is so intertwined with the teaching of entry to intermediate logic that it becomes difficult to... buttignments are typically "one word at a time" in that the target is in many languages constrained to be a single variable usually one word in size (OK, short ints and doubles may not be exactly one word). buttigning to a whole array or record in one go is not usually possible (at least in the older "clbuttical" languages). Pointers are sometimes used as a subsbreastute, you buttign a pointer to a whole object to a pointer variable, and pointers are one word long (typically). IBM 610 workstation computer 3396 Well, I know it isn't really what you mean, but what the heck... :-) They not only can be faster than needed for an application, they can be faster than can be tolerated... Backus was suggesting (and he wasn't the only person working in this area) that the fundamental operations of programming languages should be bigger, whole structure at a time, things, like "apply this operation to this structure", "reduce this structure to something simpler by applying this operation" - APL was a good example of a language with this sort of primitive, but it was too specialised to be of general use. This is not to criticise the von Neumann architectue for hardware, but to point out that there is no need for programming languages to model themselves on it. They can adopt other paradigms - all it needs is good compiler technology. Well, semantics is just what programs and language structures mean, and can be described in a number of ways. Operational semantics does this by defining language components in terms of actions on a simple machine, which is presumed to be already understood. If this machine is a von Neumann machine, these operations are mostly buttignments (loads and stores). The state of a machine is essentially the contents of its memory and registers, so buttignments change the state. If you need to reason about a program - say you are writing a compiler and are trying to do standard optimisations - you need to know what states are possible at every point of the program. For example, if you can establish that a particular computation performed in a loop is always the same, because the values it uses can't be changed by buttignment between uses, then you can move that computation out of the loop so it only gets done once. Proving properties of this kind is hard, but would be a lot easier is there were no buttignments in the source language. Backus' FP language didn't have buttignments - in this respect it is like any of the other functional languages from pure Lisp throught to ML and Haskell. In these languages, you work with values, not with places which can hold values. Values don't change, so the semantics is best described as a mathematical description of the computation, and does not involve state transitions.
In functional and similar languages, the basic operation is to apply a function to a value to get another value. Functions may be familiar mathematical ones, or more complex things like map (which applies a function given as a parameter to map, to every component of a structure also given as a parameter, to produce a new struture of the same kind) or fold (which applies a function to a structure in such a way as to reduce it to something simpler - e.g. applies "add" between elements of a numeric sequence to produce the sum of the elements). These kinds of operations make heavy use of function paramenters that are themselves functions (equivalent to "procedure paramenters" as permitted in some familiar languages) but they also allow functions to return values that are themselves functions (almost unheard of in other kinds of languages because there are difficulties with the usual stack method of handling calls and returns and local temporary storage). Such functions, which take other functions as arguments and produce new functions, are the "combining forms" he refers to. The simplest example is function composition, which you could define by something like "compose (f,g) = the function of x which is f(g(x))". Once you have the semantics of functions expressed in mathematical language, you can reason about programs by doing mathematics. The absence of state (changes) makes this much more practicable. I understand your feelings about APL. :-) Repebreastive programs have loops to iterate over data. Loops can be avoided by using recursion, and that is what most functional languages do, but Backus advocated working at a higher level, working with data structures all at once, not an element at a time, so neither iteration nor recursion is explicit in the program. As a simple example, the map function above is easy to define recursively, but if you have map and sufficient other higher-level functions given, you don't need to actually write any recursive definitions. This only works is the data structures you use are recursively (or inductively) defined. You might define a binary tree as "a Leaf value (the base case of the recursion) or a Node with a value and two binary trees as components". You can fold a function over a tree (to get the sum or product of the values, for example) but not over an ad hoc, unstructured, collection of unrelated values. Phew! (mopping sweat off forehead) --brian -- Wellington, New Zealand "What's life? Life's easy. A quirk of matter. Nature's way of keeping meat fresh."
|
||||
IBM 610 workstation computer 3393 Alt Folklore Computers from Newsgroups The #1 Usenet Provider on the Internet
|
||||