Article View: comp.lang.misc
Article #155Re: Types, arrays, generality, and notation (was: Fortran90 and Arrays)
From: Stephen P Spackman
Date: Sat, 11 Apr 1992 09:38
Date: Sat, 11 Apr 1992 09:38
222 lines
12031 bytes
12031 bytes
In article <1992Apr10.184017.10041@newshost.lanl.gov> jlg@cochiti.lanl.gov (Jim Giles) writes: |In article <STEPHEN.92Apr10055926@estragon.uchicago.edu>, stephen@estragon.uchicago.edu (Stephen P Spackman) writes: ||> [... static type tests ...] ||> Look at SELF. Hell, look at the internals of a competent FORTRAN ||> compiler. You're thinking in the stone age! :-) | |But Fortran requires declarations! If you haven't got declarations |AND you've got I/O, separate compilation, and the ability to assign |objects of _any_ type to _any_ identifier, you can't expect the |compiler to be able to do compile-time type checking very well. |It means that you must infer constraints about objects which |inherently aren't known until run-time. So delay compilation until runtime. The distinction is artificial, anyway: the cleanest and most portable description of an executable image is that it is a long-term-suspended process that is cloned and restarted.... ||> [...] ||> It's not a question of if they could according to the language spec, ||> it's a question of whether they could according to the programme text ||> as interpreted under that language spec, and those are poles apart. | |Agreed. There is much that _can_ be done even without declared variables. |But, that is not as much as is _easily_ done if you have declarations. |If you have declarations AND sophisticated techniques, you can do |better than if you have to go without one or the other. And, as |I've repeatedly pointed out, declarations make the code more legible |to _humans_. I agree with the comment; I'd like to see *much* stricter typing rules than fortran provides (the idea of being able to assign a distance to a pressure gives me the hab-dabs) for reasons of security, efficiency and self-documentation. But I still think a really good compiler will get more of its information by analysis than by declaration. And if I had to design an intermediate code I'd rather go typeless than use (at least older) FORTRAN models. Doing it right is better still. |Separate compilation and optimization are not _that_ incompatible if |it's possible for most of the optimization to be carried out on the |basis of declared attributes. The loader can include checks to make |sure the actual uses match the declarations. Register allocation, type representation selection, calling conventions, inlining, space/speed generation choices, argument format checking, exception handling, and code placement. That's probably only a quarter of the list of things that you can't get right on a module-at-a-time basis. You really are straightjacketting yourself by INSISTING on separate compilation. ||> [...] - in fact, ||> optimisation without prior execution is undesriable, too, so a decent ||> system with good performance is going to look a bit interpretive.... | |The explicit declarations available to a language _could_ include |usage statistics from test runs or preceeding versions. But self-modifying source is a worse disaster than self-modifying object. (Of course, there's a clean, standard solution in the form of compiled, automatically-derived interface files). ||> Have you considered distributing the intermediate code instead? |That's what relocatable files _are_ (like C dot-oh files). Ha ha. Try dumping one some day. Thre MAY be a few compilers that get this right (in fact Mark Rain's Mary2 was supposed to, ten years gone by), but they're not what you'd call common.... Here's the acid test: can you take your relocatable file and use it on a machine with a different architecture? I thought not.... ||> ...reaches for asbestos-type trousers... ||> ||> What, you think I'm defending J, just because I don't like FORTRAN? ||> They're practically dialects of each other anyway, with their ||> array-o-centrism, type-o-phobia, line-oriented syntax, proliferation ||> of system-reserved mechanisms, encouragement of semantically ||> inexplicable floating-point arithmetic and general inattention to ||> actually solving the problem.... |"Array-o-centrism" is an important feature for a large set of |important applications. I don't know what you mean by "type-o-phobia". No it is not. SUPPORT for arrays is important - surely important enough to justify that arrays be ONE of the type-construction methods directly supported by the standard library. But giving it a distinguished syntax is perhaps going too far - and giving it 90% of the operator namespace (as in J) is criminal. And by "type-o-phobia" I intended to suggest an attitude that types are a "magic" mechanism which the user can't be allowed to use on hir OWN behalf, to solve actual problems.... |To be sure, Fortran hasn't got a complete set of type construction |tools (Fortran 90 makes this worse by introducing explicit pointers |as the only mechanism for recursive data structures, etc.). I don't |know what you mean by "line-oriented syntax" either, but human factors |experiments have shown that people intuitively use lines in certain |ways and languages which don't conform to these ways induce larger |numbers of errors. What's a "system-reserved mechanism"? Come up System-reserved mechanisms: fortran has keywords and weird syntaxes for this and that. J reserves all the little squigglies for its own use. Neither of them lets you introduce a new class of literals (even one so simple as, say, frequencies).... It's not always attainable, but if there are TWO of a kind of thing (any kind of thing) in a language, you have to ask yourself why the programmer can't decalare more.... |with an efficient method of calculating without floating-point and |I suspect Fortran (even J) would be quickly extended to support it. Fixed point with the compiler tracking the scaling factor, of course. Von Neumann pointed this out, and I concur: there aren't enough things in nature with a dynamic range in excess of 2^64 to justify giving hardware support to floating point; what it's actually USED for is to avoid thinking about dynamic range at all, and that leads to bugs. In principle we could have 128-bit integers that are significantly faster than IEEE floating point - and a lot more useful - and I think it's really stupid that the FORTRAN community has such a stranglehold on hardware architecture that people don't wake up and start demanding good support for integers. And if you really *need* fp, for that one case in a million, software emulation isn't so bad: given an extra 64 guard bits you can probably forestall normalisation for a LOOONG time. (Cogent comments welcome, flames not. Bin having this argument for too long to want a fist fight over it anymore...). |As for "actually solving the problem", most of the other things you |mentioned are required in order to make "solving the problem" possible. |The problem is to run large scientific/numerical calculations on existing |hardware with existing software technology. The existing hardware is |too slow, has too little memory, and the existing software technology |is inadequate at automatically making best use of the existing speed |and space based on a purely abstract problem definition. Am I arguing? I just think that getting locked in worse is stupid. ||> |[...] ||> |Ok. This could be defined as the operation of REDUCE. You'd have ||> |to add a way of passing the identity element (and a way of stating ||> |that there isn't one). ||> ||> Gotta be one, if you're going to go the directional route. But you can ||> always use the end element of the array if you are SURE that's what ||> you want. | |I thought the identity element was returned for _empty_ arrays. The |end element of an array doesn't exist in this case. What you want is |to give the _user_ the option of stating whether this should be considered |an error or not. So, you pass an identity element as an additional |optional argument to reduce and if it is omitted you treat empty arrays |as errors. Nono, you missed the point. Some operations (like "+") make SENSE for empty arrays, and there you supply the appropriate value (0). Others (like "min") only make sense on an empty array in an extended domain (for present purposes: don't make sense) and so you REQUIRE at least one element, pass THAT as the identity, and then reduce the REMAINDER of the array (which will now be length 0 if the original was length 1). The tree is like this: /\ x /\ y /\ z i with i, the "identity", in the end position, which is syntactically and semantically disitinguished - as I pointed out, it can even have a different type. That's one of the other things that's different about the "random tree" version, incidentally: it HAS to be symmetric. |I don't question the possibility of such a thing, but what would anyone |use it for? As I said, I'll take you word for it that it _may_ be |useful, but I think I'd rather have the default version of `scan' not |allow it - such a rarely needed feature, if accidentally used, is almost certainly just an error. Can you givean example of an algorithm which |can make sensible use of unordered scan results? Yes. You are searching in a tree, and you want to use the natural tree structure and not get it flattened to a vector. I *don't* know of a language with a type structure in which this very practical problem can be made to drop out notationally though - but wait another five or ten years, and you'll see it cropping up. It'll look like an alternate interface that makes an automatic coercion (an interface inheritance, actually) unnecessary. |For example: let's scan addition across an list of integers (1,3,5,7,9). |What happens if the result is (16,8,5,15,25) [I summed from the middle |element out, alternating left and right]? Is this meaningful to any |algorithm you know? You need to use "cons" instead of "+" to see how it might be interesting - "+" has the wrong algebraic properties for this operation, and that ought (in principle) to be a static type error. |Haskell doesn't have these functions extended to directly handle |multi-rank arrays, much less arbitrary directions through them. |Such capability can only be handled by mapping the array into a |list of sub-arrays (along the desired axis) and defining the |function `f' on those sub-arrays. Which is fine. Doesn't involve any runtime overhead if it's done right (ha ha). |By the way, at this point I've spent about the same amount of time |studying Haskell as J - cumulatively about five hours each. I find |Haskell much more legible and easy to use (which isn't saying much). |Given that Haskell is a strict functional language and J isn't, if |the argument is that there is an advantage to functional programming, |then Haskell must be better according to that measure. It's still a dog, but it's a friendly dog. I'm with you on that. ---------------------------------------------------------------------- stephen p spackman Center for Information and Language Studies stephen@estragon.uchicago.edu University of Chicago ----------------------------------------------------------------------
Technical Details
Message-ID:
<STEPHEN.92Apr11043808@estragon.uchicago.edu>Path:
arc1-ca.pugleaf.net!sparky!uunet!cs.utexas.edu!asuvax!ncar!uchinews!tira!stephenReferences:
<ROCKWELL.92Mar21001252@socrates.umd.edu> <STEPHEN.92Apr10055926@estragon.uchicago.edu> <1992Apr10.184017.10041@newshost.lanl.gov>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!cs.utexas.edu!asuvax!ncar!uchinews!tira!stephen From: stephen@estragon.uchicago.edu (Stephen P Spackman) Newsgroups: comp.lang.misc Subject: Re: Types, arrays, generality, and notation (was: Fortran90 and Arrays) Message-ID: <STEPHEN.92Apr11043808@estragon.uchicago.edu> Date: 11 Apr 92 09:38:02 GMT References: <ROCKWELL.92Mar21001252@socrates.umd.edu> <STEPHEN.92Apr10055926@estragon.uchicago.edu> <1992Apr10.184017.10041@newshost.lanl.gov> Sender: news@uchinews.uchicago.edu (News System) Organization: University of Chicago CILS Lines: 222 In-Reply-To: jlg@cochiti.lanl.gov's message of Fri, 10 Apr 1992 18:40:17 GMT