Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!ucbvax!DMAFHT1.BITNET!X903 From: X903@DMAFHT1.BITNET (Marc Wachowitz) Newsgroups: comp.lang.modula2 Subject: Re: Make the language Perfect/SOS Message-ID: Date: 26 Jun 91 09:46:44 GMT References: Sender: usenet@ucbvax.BERKELEY.EDU Reply-To: Modula2 List Organization: The Internet Lines: 87 On Tue, 25 Jun 91 09:25:58 EDT Greg Granger said: >correctly. Consider adding unary and binary operator overloading, >via a preprocessor step (this is to support my claim of no run-time >checking and limited compiler overhead). >Example syntax: (normal preprocessor special id symbols omitted) Sorry, but I think this argument is rather nonsensical. When talking about overhead (i.e. complexity or runtime cost), "compiler" is any- thing you have to run to obtain the object file (or whatever you have instead) from your source. It doesn't matter if this is separated into several programs, or if one of them is called preprocessor. >Binary operators can be handled in much the same way and could encompass >precedence. >Consider: >BINARY OPERATOR Type1 '+' Type2 Type3 USES AddTypes23 PRECEDENCE 10; >BINARY OPERATOR Type1 '+' Type3 Type2 USES AddTypes32 PRECEDENCE 10; >BINARY OPERATOR Type1 '*' Type2 Type3 USES MulTypes23 PRECEDENCE 20; >BINARY OPERATOR Type1 '*' Type3 Type2 USES MulTypes32 PRECEDENCE 20; >BINARY OPERATOR Type1 '**' Type2 Type3 USES RaiseTypes23 PRECEDENCE 30; >BINARY OPERATOR Type1 '**' Type3 Type2 USES RaiseTypes32 PRECEDENCE 30; > >Or Perhaps just: > >BINARY OPERATOR Type1 '+' Type2 Type3 USES AddTypes PRECEDENCE 10 >COMMUTES; (* hope I got that right, long time out of math :-) *) >BINARY OPERATOR Type1 '*' Type2 Type3 USES MulTypes PRECEDENCE 20 >COMMUTES; >BINARY OPERATOR Type1 '**' Type2 Type3 USES RaiseTypes PRECEDENCE 30 >COMMUTES; (I hope you don't want to say that e.g. 2 ** 1 = 1 ** 2? :-) The problem with this approach to precedence is that it requires a global (i.e. across modules) knowledge of all operators that may be used together at some later time somewhere - probably in ways the original author never dreamed of. That's my most serious concern against this "feature": I consider it a strong attack against reuse and maintenance of large systems. All those "nice features" look quite innocent when you are doing everything alone, but may cause horror to someone who has to maintain code written by many others (and that's what we all want to be feasable, isn't it?). >and/or built into the language/compiler. Readability and abuse are >valid concerns, but not sufficient to discard consideration of such >a valuable feature. (BTW, nowhere did I say I wanted to write such Well, that's where our opinions differ - I consider readability much more important than ease of writing (this does not imply that I liked Ada, though I appreciate that readablity was one of its main design goals). >Second: MODIFY PARAMETER PASSING FOR GENERIC PARAMETERS. Perhaps have a look at Modula-3, it may have solved many of the problems you are addressing. Treat all those "generic" types as pointers. Then in Modula-3 you can declare the "generic" variables as "REFANY", and assign to it every (traced, for those who know it) pointer. It is possible to test the actual type, since every pointer type has a unique typecode associated with it. Of course, objects are the better solution in most of those cases. Modula-3 does also offer several additional features which can be used to write generic code, look into the report if you want to know more about it. Variable-length argument list can the just be implemented as open arrays of REFANY/objects etc., particularly as you have very flexible means to denote constructors for complicated types). >Pet Peeve: Consistency across systems. >I wish that INTEGERs and CARDINALs were defined by default to be 32bits, >basically I'd like to see all atomic types defined at the bit level. >Further (u didn't think I would stop there did u :-), I'd like to see >the ability to 'build a variable' at the bit level. >Example > littleCard: BITFIELD RANGE 0..15; (* 4 bits *) > bigCard: BITFIELD BITS 96; (* 96 bits *) > largeInt: BITFIELD BITS 64 SIGNED; (* 64 bit signed number *) Again Modula-3 has (is?) the solution to this problem. There is just one type INTEGER, which can be expected to be the largest reasonable signed whole number type for a given implementation - though this need not be 32 bits on every architecture. Then you have subrange types (CARDINAL is just the non-negative subset of INTEGER, thus eliminating all those nasty problems when signed meets unsigned). If you need a low-level mapping, there are packed types, of the form BITS NumberOfBits FOR BaseType where BaseType can be any type, not only numeric types. Thus you can just state what your precise requirements are for a given problem. Of course, not every possible size will be possible on all architectures, but the inablitiy of an implementation to give you what you requested is a static (i.e. usually compile-time) error. The report on Modula-3 and the implementation (as far as I know it's yet the only one) for various U*X-systems is available by anonymous ftp on gatekeeper.dec.com, directory /pub/DEC/Modula-3. Marc Wachowitz X903@DMAFHT1.BITNET