M-FAQ HTML version prepared by Dan Baer
Archive-name: m-technology-faq/part1 Last-modified: 1997/08/01 Version: 1.6 Posting-Frequency: monthly M Technology and MUMPS Language FAQ
This FAQ is copyright ©1997 by Gardner S. Trask III. All rights reserved. Permission is granted for this FAQ to be redistributed provided:
Post comments or suggestions to comp.lang.mumps or email to trask@world.std.com .
NOTE: This document contains URL's and addresses that were acurate at the time of the original inclusion. URL's and e-mail addresses change however, and will (when notified) be reflected in Appendix 10. So, if you wish to reach a contributor, confirm addresses there.
Editors
Questions that need answers:
Changes since version 1.5: 5/1/97
Ben Bishop Jon Diamond John D. Godfrey Gavin Greig Russell Haddleton Scott P. Jones John E. Kemker, III Mark Komarinski Jeff Loeb Keith F. Lynch Ed de Moel Steve J. Morris Kevin O'Gorman Doug Preiser Aaron Seidman Kate Schell Tilman Schmidt Arthur B. Smith Daniel P. B. Smith Richard J. Tomlinson Gardner Trask David Whitten Indirect Contributors: Those for whom postings and approved e-mail was included. Ellis A. Bauman Dennis J Brevik Etienne Cherdlu Floyd Dennis Rod Dorman Lev Jacob Monika Kratzmann Paul Perrin
Appendix 1: List of M Vendors
Appendix 2: The M Technology Association
Appendix 3. USA Local M Users Groups
Appendix 4: Is the official name of the
language "M" or "MUMPS?"
Appendix 5: A "secret decoder
ring:" highlights of the M language
Appendix 6: An example of
"textbook" M coding style
Appendix 7: An example of
"traditional" M coding style
Appendix 8: MUMPS - A solution looking for a
problem.
Appendix 9: Tributes, Accolades and
Honorable Mentions outside the M Community
Appendix 10: Contact information: e-mail and
URL's
Appendix 11: FAQ Change history
M is a procedural, interpreted general-purpose programming language oriented towards database applications. Its characteristic features are:
[Tilman Schmidt (ts@gb1.sema.de), ed. DPBS]
M has many good points: high productivity, low hardware requirements, good scalability. But M also has some weaknesses: low transaction reliability, character-based screens, poor integration with other environments, and few development tools. [Thomas C. Salander, M Computing, June 1994, p.74]
M is a lousy language with one great data type. [Steve J. Morris, sjm2@shore.net]
Massachusetts General Hospital Utility Multi-Programming System.
A programming language with extensive tools for the support of database management systems. MUMPS was originally used for medical records and is now widely used where multiple users access the same databases simultaneously, e.g. banks, stock exchanges, travel agencies, hospitals.
Early MUMPS implementations for PDP-11 and IBM PC were complete operating systems, as well as programming languages, but current-day implementations usually run under a normal host operating system.
A MUMPS program hardly ever explicitly performs low-level operations such as opening a file - there are programming constructs in the language that will do so implicitly, and most MUMPS programmers are not even aware of the operating system activity that MUMPS performs.
Syntactically MUMPS has only one data-type: strings. Semantically, the language has many data-types: Text strings, binary strings, floating point values, integer values, Boolean values. Interpretation of strings is done inside functions, or implicitly while applying mathematical operators. Since many operations involve only moving data from one location to another, it is faster to just move uninterpreted strings. Of course, when a value is used multiple times in the context of arithmetical operations, optimised implementations will typically save the numerical value of the string.
MUMPS was designed for portability. Currently, it is possible to share the same MUMPS database between radically different architectures, because all values are stored as text strings. The worst an implementation may have to do is swap pairs of bytes. Such multi-CPU databases are actually in use, some offices share databases between VAX, DEC Alpha, SUN, IBM PC and HP workstations.
Versions of MUMPS are available on practically all hardware, from the smallest (IBM PC, Apple Macintosh, Acorn Archimedes), to the largest mainframe. MSM (Micronetics Standard MUMPS) runs on IBM PC RT and R6000; DSM (Digital Standard Mumps) on the PDP-11, VAX, DEC Alpha, and Windows-NT; Datatree MUMPS from InterSystems runs on IBM PC; and MGlobal MUMPS on the Macintosh. Multi-platform versions include M/SQL, available from InterSystems, PFCS <mumps@pfcs.com> and MSM.
Greystone Technologies' GT/M runs on VAX and DEC Alpha. This is a compiler whereas the others are interpreters. GT/SQL is their SQL pre-processor.
ISO standard 11756 (1991). ANSI standard: "MUMPS Language Standard", X11.1 (1977, 1984, 1990, 1995?).
The MUMPS User's Group is known as the M Technology Association.
Mailing list: MUMPS-L@UGA.BITNET.
Usenet newsgroups: comp.lang.mumps, comp.std.mumps.
(10 Jan 1995) [Submitted by: "Daniel P. B. Smith" Original Author unknown]
(11/94) comp.lang.mumps (read c.l.mumps) is a "USENET newsgroup." It was created in July, 1994. It is an unmoderated newsgroup; anyone can post messages to it and anyone can read all the messages posted to it.
The newsgroup's charter is given below. The charter is what was voted on by the USENET community when the group was created. As with all unmoderated newsgroups, the health of the newsgroup depends on goodwill, courtesy, and voluntary adherence to the spirit of the charter. Since its inception, comp.lang.mumps has been a friendly newsgroup with a comfortable volume, typically one to five messages per day. Recent topics have included: M coding standards/practices/conventions; rumors about possible M vendor mergers; job postings; and inquiries about specific problems with particular M implementations.
CHARTER of comp.lang.mumps
The proposed unmoderated newsgroup comp.lang.mumps will be open to discussions on almost all topics related to versions of the M technology and the M language (also known as MUMPS). Appropriate topics would include, but not be limited to:
The only topic that is excluded is: discussion of the standard for the M (MUMPS) language, ANSI X11.1 which should be discussed in the existing group comp.std.mumps.
Subsequent custom has established that informal discussions of standards- related issues are very welcome in this newsgroup. MDC members have suggested that they welcome informal discussions be conducted in comp.lang.mumps, while formal proposals should be posted to comp.std.mumps. It is also clear that the membership welcomes job postings and job information.
SUBSCRIBING TO COMP.LANG.MUMPS
There are different kinds of Internet access. One common situation is a
company that "has Internet access" via their internal e-mail system.
Such arrangements often are e-mail only; if so, you must use the "MUMPS-L
gateway" access method described below. Other sites have direct access to
the USENET newsgroups. This is common for academic and government sites, and
commercial services. Find out whether your site has direct access to the
newsgroups. If you have it, this is the best way to read and post to
comp.lang.mumps. If you are on a typical UNIX host at an academic or government
institution, one way to check is to type the names of the most popular
"newsreaders" -- rn, trn, tin, and nn -- at the command prompt and
see if any of them are installed. If not, you probably do not have USENET
access and should use the MUMPS-L gateway. If you find that a newsreader is
installed, consult an Internet-savvy colleague, system administrator or help
desk for more information. (11/94) Most of the commercial services, including
America On-Line, CompuServe, DELPHI, and Prodigy now offer direct newsgroup
access. Details for CompuServe are noted below.
THE MUMPS-L GATEWAY
(8/94) Anybody with Internet E-mail can participate in comp.lang.mumps by making use of a gateway and mailing list provided by American University and BITNET. Out of courtesy to the host organization, please use this method only if you cannot get access to comp.lang.mumps in any other way. For those who CANNOT get comp.lang.mumps in ANY other way: To receive MUMPS-L and comp.lang.mumps: Send an e-mail message To: LISTSERV@uga.cc.uga.edu The subject line doesn't matter. The message text should consist of the single line: SUBSCRIBE MUMPS-L Within a short time, you'll get an automated acknowledgement from the list server confirming your subscription and giving other information, and you'll start getting the comp.lang.mumps and MUMPS-L posts. To post a message to MUMPS-L and comp.lang.mumps: Send an e-mail message To: MUMPS-L@uga.cc.uga.edu IMPORTANT: NOTICE THE DIFFERENCE IN THE ADDRESSES. To start and stop subscriptions, you address the request to LISTSERV. Thanks to: American University, for hosting and operating the gateway; Jim McIntosh, jim@american.edu, for administering it; Harold Pritchett, harold@UGA.CC.UGA.EDU, owner and administrator of the MUMPS-L list; and the BITNET organization generally.
COMPUSERVE
(1/95) Some users have advised making sure that you understand CompuServe's rates, terms, and conditions before using CompuServe to access comp.lang.mumps, as the charges may be higher than anticipated. As of 11/28/94, according to a CompuServe representative (Julie Borders), Newsgroup access is an "extended service" charged by the hour at the same rate as other extended services. "To send Internet e-mail it is $.15 for the first 7500 characters and $.05 for each additional 2500 characters. It is the same rate to receive Internet e-mail." -- [DPBS] (11/94) CompuServe now offers direct newsreader access to the Usenet newsgroups. CompuServe subscribers may already using the MUMPS-L gateway, as described above. If you are doing this now and are satisfied with this system, there's no need to change. Here are the steps I took to read comp.lang.mumps on CIS. Depending on exactly how you're set up (for example, whether you're using CIM), the details may be different for you, but everything should be clear once you GO USENET. For me: the steps were I typed "GO USENET" I chose #6, "USENET Newsreader" I read some pages of warnings, disclaimers, and advice I chose #3, "Subscribe to newsgroups" I chose #1, "Subscribe to one known newsgroup" I typed "comp.lang.mumps" in response to the prompt "Newsgroup name" I typed "m" to return to the previous menu I chose #1, "Access your USENET newsgroups." It listed "comp.lang.mumps (18 articles) " as the only newsgroup I'm subscribed to, then offered choices. I chose #3, "Read articles" --[DPBS]
The following books can be ordered from any M Technology Association. Contact them for prices. In the USA, contact:
M Technology Association
1738 Elton Road Suite 205
Silver Spring, MD 20903.
Telephone +1-301-431- 4070.
Introductory/Tutorial:
Other:
MUMPS POCKET GUIDE - 1990 by Joel Achtenberg, revised by Thomas C. Salander (MTA item #2018)
A COOKBOOK OF MUMPS by David B. Brown & Donald H. Glaeser, D.Sc.(MTA item #2024)
Introductions and Tutorials:
High productivity, low hardware requirements, good scalability. [Thomas C. Salander in M Computing, June 1994, p.74]
I still program with other languages (Pascal, C, APL, LISP, and so on), but almost always find myself saying, 'but it's so much easier in MUMPS!' ... it's just plain quicker to implement most applications MUMPS. MUMPS is a powerful computing language designed to solve real-world problems. [John Lewkowicz, The Complete MUMPS, p. xii]
When I was first at the VA, Greg here gave me a 1 page batch of M code and asked if I could do it any faster in C. Two weeks, a lot of aspirin, and two compilers later, I had 'barely' working code (it would only run *once*). [Mark Komarinski, komarimf@craft.camp.clarkson.edu]
M is powerful and succinct. It's excellent for general hacking. If I suddenly get a hankering for the first thousand digits of pi, or for all the order 4 magic squares, or for a table of word frequencies in a document, I don't know of any language I can accomplish this in faster. [Keith F. Lynch, kfl@access.digex.net]
f p=2,3:2 s q=1 x "f f=3:2 q:f*f>p!'q s q=p#f" w:q p,?$x\8+1*8 [part of Keith Lynch's .signature; it prints a table of primes, including code to format it neatly into columns -- DPBS]
I really like the way that the global tree is "just there" without any file opening, record declarations, and the like. [Kevin O'Gorman, kevin@kosman.uucp]
Indirection. Execute strings. String subscripts. Enormously valuable. No other language has all of them. [Ricardo Garcia]
I haven't touched MUMPS since the late 70's. I`ve been missing globals ever since. While I was using MUMPS I implemented a simple programming tool couple of pages of MUMPS code. I've missed that tool ever since, as well as how easy it was to implement. [Steve J. Morris, sjm2@shore.net]
Low transaction reliability, character-based screens, poor integration with other environments, and few development tools. [Thomas C. Salander in M Computing, June 1994, p.74]
Are all vendors utilities crap? Having worked with DTM, DSM, MSM it seems lots of effort went into the M and no thought went into the programmer utilities. [Richard J. Tomlinson, Richard@rtsysgen.demon.co.uk]
When I look back on my Fortran code from school I am a little embarrassed but I understand it. When I look back on my MUMPS I can't even read it without slow token by token translation. It's amazing to me how fluent I was when I wrote it and how fluent I'm not when I read it. [Steve J. Morris, sjm2@shore.net]
It's possible to write completely obfuscated MUMPS code, and too many MUMPS programmers do it. Some even brag about nobody else being able to read their code. Fortunately for those of us in the VA who have to maintain that code, they are becoming a minority. [John E. Kemker, III, kemker.j@atlanta.va.gov]
M is a programming language with a strong emphasis on text handling and database management. However, M is NOT a data base management system. The disadvantage of being a programming language is that it takes more expertise to apply the language to create a working data base, but the advantage of not being a dedicated database management system is that it is infinitely more flexible. [Ed de Moel, demoel@saltmine.radix.net]
The so-called DBMS component of M is another name for the feature of persistent associative array variables, i.e. arrays that can be indexed by strings, on an arbitrary number of levels, and that survive the termination of the program, being transparently stored on a permanent medium (hard disk). This feature is comparable to what ISAM (Indexed Sequential Access Method) packages offer for other languages, but it is more powerful than ISAM and it is seamlessly integrated into the language. It is *not* a relational database system, although it can serve as a basis for implementing one and does so in several commercial products. [Tilman Schmidt (ts@gb1.sema.de)]
Databases that have a lot of many-to-many relations, and/or a lot of sparse information (fields that are more often empty than filled in) do not fit the relational model well. While a relational database can represent this data, it does it with great complexity or inefficency. The sparse hierarchical array structure assumed by M is a much more natural fit for this type of data. [Arthur B. Smith, ART@vets.vetmed.missouri.edu]
The M standards suite includes a standard for embedded SQL, and embedded SQL is provided in commercial products such as InterSystems' M/SQL and KBase's KB/SQL. [David Whitten, whitten@netcom.com]
Initial development of the "relational model" of databases appeared to place MUMPS at a disadvantage, but recent advances in so-called non-first-normal form, a reference to hierarchical structures characteric of MUMPS, open the door for MUMPS to take a leadership role in current research in that field. [Richard F. Walters, "The ABCs of MUMPS"]
M was designed to be interpreted. Real compilation of an M program into a machine program for the target machine is not feasible due to the following of M's features:
[Tilman Schmidt (ts@gb1.sema.de)]
Greystone has a product that compiles to .EXE files that are comparable in size to C source .EXEs. [David Whitten, whitten@netcom.com]
Most of the versions of MUMPS these days are pre-compilers; a tokenized version of the routine is actually stored separately and usually runs faster. [Ben Bishop, aci@world.std.com]
The reasons to use a pseudo-code approach instead of trying to generate machine code has a lot to do with memory efficiency - M has a well deserved reputation for requiring very little in the way of hardware resources, such as RAM. It also has a lot to do with what people do in M. If you do profiles on M applications, you find that much of the time they are doing things that wouldn't be helped by trying to compile to assembly code anyway (they are accessing globals, doing I/O, etc.). Also, with a good C implementation of M, I can port to a new Unix platform in a day or so (and then take a few weeks more if we want to assembly optimize the most commonly executed simple tokens - which I have done for most of the current architectures (Intel, Alpha, Mips, RS/6000-PowerPC, Motorola 68K, Motorola 88K, and Sparc). That would not be possible with an implementation that actually compiled to machine code. (Look at the delays of moving VC++ 2.0 to non-Intel architectures). Finally, with pseudo-code (we call ours m-code), you can share a compiled routine across all platforms (as we do with our M/SQL code). [Scott P. Jones, scott@INTERSYS.COM]
One company developing heavily in MUMPS ran tests to determine performance characteristics of MUMPS vs. Oracle. MUMPS ran approximately six times faster. Digital's DSM (Digital Standard MUMPS) consistently sets benchmark records for transaction processing. [John E. Kemker, III, kemker.j@atlanta.va.gov]
In benchmarking MUMPS and alternatives such as RPG, BASIC, COBOL and FORTRAN, Casimiro Alonso reports that "A user choosing MUMPS for interactive data base applications can expect up to five times more power from a given computer" and that "the applications development took about one-third the amount of time forecast for the use of other languages...." with the MUMPS database occupying "only one-half to one-quarter of the disk space required by others. [C. Alonso, A Case for MUMPS, Computerworld, January 9, 1984, as cited by William J. Harvey and Frederick G. Kohun in the article, "MUMPS," from Encyclopedia of Microcomputers, 1993.]
Very rough tests suggest that DTM is about twice as fast as Visual BASIC's implementation of the BASIC language. These tests involve simple code, coded similarly in each language, that exercise fundamental operations that are common to, and natural in, both languages (FOR loops involving arithmetic and fundamental string operations). On a 33MHz 386DX, Visual BASIC runs at very roughly 1000-2000 commands/second, DTM about twice that. Double that for a 486 DX2, quadruple that for a Pentium. [DPBS]
A 1994 addition to the M standard, the M Windowing API (MWAPI), defines an interface between the M language and windowing systems. InterSystems and Micronetics offer versions of M that implement the MWAPI in a Microsoft Windows environment. Digital has an implementation [is it commercially released? Details?] for Windows NT. The M Windowing API and its commercial implementations are relatively new and have rough edges. The MWAPI has the advantage of portability and platform-independence, but has some limitations associated with the "least- common-denominator" approach. A unique feature of the MWAPI is that this "API" does not consist of subroutine calls (except for a few incidental functions). MWAPI programming consists mainly of performing sets and kills into a "structured system variable," which looks like a standard M global. For example, to set the title of a window to "M Technology Demonstration," you write
S ^$WINDOW("main","TITLE")="M Technology
Demonstration"
To make its dimensions 300 by 200, you write
S ^$WINDOW("main","SIZE")="300,200"
The MWAPI is currently offered for Microsoft Windows by InterSystems and Micronetics, and for Windows NT by Digital Equipment Corporation. It is often presented as the windowing future for M technology.
VISUAL-BASIC-LIKE APPROACHES
InterSystems' "Visual M" is a set of tools which link M with Microsoft Visual Basic, creating an integrated dual-language environment. M code can be accessed and edited from within the VB design environment, can access VB control properties, and can be triggered by VB events. Micronetics [product name????] provides a Visual-Basic-like environment entirely based on M and the MWAPI. "WRITE-SLASH" APPROACHES InterSystems' "DT-Windows," MGlobal's MGM-PC (for MS-Windows) and MGM-Mac (for the Macintosh) use a feature of the M standard that allows the language to be extended for device-specific purposes by means of the "write-slash" syntax. In DT-Windows and MGM, the windowing system is treated as a "device" with an unusually rich repertoire of device-specific commands.
Although DT-Windows and MGM are conceptually similar, they are incompatible
with each other. They are ad-hoc language extensions. Neither seems to have set
a defacto standard. Why do these products (DT-Windows and MGM) provide a
nonstandard approach? The answer, in part, is that they were introduced prior
to the finalization of the MWAPI standard. Why do they still exist? Because
they are closer to their underlying windowing platform than the MWAPI, they
arguably provide better performance and broader access to the GUI system's
functionality. Examples from the DT-Windows manual and MGM product literature,
respectively, show how an "OK" button is added to a dialog box:
DT-Windows:: w
/waddbutton(2,65,40,10,20,1,1,1,0,0,0,"OK",1)
MGM:: W /DBUTTON("OK",2,9)
The M Technology Association publishes "M Computing," a technical journal. Members receive it free. See Appendix 2. MTA-Europe publishes "M Professional" a news/technical journal in English 3 times a year. MTA-Europe members receive it free. Non-members can order a subscription. Other MTAs also produce newsletters, mostly in local languages. Contact them directly for more information.
This topic seems to be the M community's very own little religious war. The following represents the editor's opinion. Other views, including one from a member of the MUMPS Development Committee, are represented in Appendix 4.
M and MUMPS are alternate names for the same language. M, the newer name, is now very widely accepted in the M community. The name change was introduced to address long-standing problems with the name MUMPS. The name MUMPS gave many the impression that the language was specifically for hospitals and health care applications. Many also felt it was undignified. M/MUMPS has evolved rapidly, with new ANSI standards being successfully issued in 1977, 1984, 1990, and a new standard now in canvass, which will probably issue in 1995. It is not the same language that it was in 1967. [DPBS]
1991 worldwide revenue in the M marketplace was estimated at $1 billion, projected to grow to $2 billion by 1996. Approximately 2,000 individuals/organisations belong to M Technology Association-North America, with approximately another 1,000 belonging to other MTAs. Versions of the M language are available from twelve vendors on every significant hardware platform. Some versions provide direct support for non- English languages, for example German, Russian, Japanese. But: "The national meeting of the MTA draws fewer attendees than the northeast regional meeting of the SAS Users' Group." [Thomas C. Salander, M Computing, June 1994, p. 72].
Although it originated in a medical environment, nothing in the language is specific to medical applications. Non-medical applications can be, and have been, implemented successfully in M. The Gartner Group report, "1992 MUMPS Assessment and Opportunity," notes:
"[M-based trust software from NCS] is used by several of the top 200 U.S. banks to control more than 375 accounts totalling $600 billion in trust assets. Lloyds of London, Barclays, and Bank of Bermuda ... use M systems... M moved into communication, shipping and transportation, law enforcement and other areas in the 1970s and 1980s. The Veteran's Administration, Discovery Channel, Coca-Cola and Schweppes, Ltd. Star Shipping, and the Law School Admission Service are among the M users."
A recent M Technology Association press release describes how M Systems Plus won a contract with American Express's Travel Related Service Division (AMEX) in Atlanta contract to convert 2,000 cruise bookings acquired from a West Coast firm. It is said that the M System was designed and developed within two and a half weeks, and was up and running on schedule, processing over 500 telephone booking inquiries the first day. It has since been expanded to include brochure fulfillment, customer service, word processing, questionnaires that gauge customer reaction, and agent telephone activity tracking. [DPBS]
No. A working group within MDC (the MUMPS development committee) is, however, actively considering object-oriented extensions. One vendor, ESI is marketing a development system, ESIObjects, that allows fully object-oriented programming in M. [DPBS]
ESI, 5 Commonwealth Road, Natick, MA 01760 1-508-651-1400, FAX 1-508-651-0708However, M has many of the characteristics of newer OO languages. For example: dynamic memory usage, late-binding, encapsulation possibilities. [Jon Diamond, jdiamond@hoskyns.co.uk]
Yes, no, maybe, sort of. M syntax is not for purists or academicians. If you want to code in a structured style:
M does not enforce a structured style. And because the features that support structured programming were absent from the MUMPS of the early eighties, there is a substantial body of unstructured legacy code still in use, and a substantial number of M programmers comfortable with what might be called the "traditional" coding style.
The M "ELSE" statement is a simple executable statement. It is not syntactically paired with an IF. The semantics are, approximately:
An IF statement sets the value of $TEST according to whether the condition was true or false. An ELSE statement is equivalent to IF '$TEST (the apostrophe is the "not" operator). Unfortunately, the traditional MUMPS subroutine does not push and pop the state of $TEST. Thus,
If a>b Write !,"a is greater."
Else Write !,"b is greater."
performs as expected, but
If a>b Do REPORT1
Else Do REPORT2
may not, particularly if the REPORT1 subroutine itself contains If statements of its own.
This problem is solved by a feature called the "argumentless Do." Actually the argumentless Do plays three separate roles in M programming:
If condition1 Do ;;executes if condition1 & 2 are true
.If condition2 Do
..<code>
..<code> ;;executes if condition1 is true but not condition2
..<code>
.Else Do
..<code>
..<code> ;;executes if condition1 is fales
..<code>
Else Do
.<code>
.<code>
.<code>
[DPBS]
Is MUMPS structured? I think it is. We haven't outlawed the GOTO true, but we have named subroutines, controlled loops (while loop is the same as argumentless FOR with a QUIT), iterated loops (FOR), Parameter Passing to subroutines, functions with return values... We also have line scoping on IFs, ELSEs and FORs. What else do you need to be structured? [David Whitten, whitten@netcom.com]
What about declaration of variables? What about scope of variables aside from line scope? I'm not convinced that the "while" exactly counts as a feature of MUMPS - in fact, an argumentless FOR with a QUIT is a "repeat...until", for a "while" you would need to perform an initial IF. Do such composite statements really count as proper controlled loops? Even if MUMPS is technically structured, it goes (IMHO) against the spirit of structured programming with commands reduced to a single letter whenever possible, short variable names encouraged, and no white space. The significance of the space character (in argumentless commands) is completely counter intuitive. I can't say that technically you're not correct in mentioning the above features but one of the primary aims of structured programming is to make support of existing code easier. In my experience, MUMPS encourages hacking and badly designed code. [Gavin Greig, ggreig@mcs.dundee.ac.uk]
Yes. An important feature of the M language is that the standard language core includes multiuser and multitasking features. These facilitate writing portable distributed-processing applications. A "JOB" command allows one process to initiate other, independent processes. Processes can arbitrate access to resources with each other via a "LOCK" command. There is no specific formal interprocess communication. Interprocess communication is achieved via the LOCK mechanism and shared use of "global" data (which are available to all processes) [--DPBS]
Yes. The primary method of implentation might be termed "remote global access." Globals residing on a remote system can be accessed and locked simply by using extended syntax to refer to them. For example,
^HERE(name,address)
refers to a piece of data on my local system, while
^|DENVER|THERE(name,address)
might refer to a piece of data on a remove system. Thus, the same programming techniques used to build multiuser and multiprocess applications on a single system can be used to build distributed network systems.
In addition to this explicit networking most vendors allow for implicit network referencing, allowing system managers to choose the location of data independent of the application programs. A networking protocol standard, "Open MUMPS Interconnect," provides least- common-denominator capability so that systems from different vendors can participate on the same network. In addition, for competitive reasons, most vendors support the major protocols of their competitors. An M-based LAN system in use at Brigham and Women's hospital, with 3,000 PC clients and over 100 servers, is a well-known and very successful application of the technology. There are also a number of systems with M operating in more complex client/server situations, with M acting as a front-end to other systems and also a back-end via RPC etc to applications created using other tools, for example Visual Basic, C++ and so on.
1977: accepted as an ANSI standard, ANSI/MDC X11.1 1984: revised ANSI standard ANSI/MDC X11.1-1984 1986: approved as a Federal Information Processing Standard (FIPS) 1990: revised ANSI standard ANSI/MDC X11.1-1990 1992: accepted as an international standard, ISO/IEC 11756-1992 1993: revised FIPS 125-1 1994: revised standard currently in ANSI canvass procedure for approval as ANSI/MDC X11.1-1994 (or maybe 1995) and distributed for comments in ISO as ISO/IEC 11756-1995. [DPBS, compiled from others' comments]
As a standardized language, M is portable as long as only the features defined in the standard are used. In practice, the portability of M programs is typically as good as or better than that of C, and much better than BASIC, because, unlike BASIC for example, standard MUMPS is sufficiently rich to implement real-world applications mostly without resorting to vendor-specific extensions. [Tilman Schmidt, ts@gb1.sema.de]
The contents of the ISO standard is IDENTICAL to the contents of the ANSI standard. This is another thing that makes M[UMPS] special: it is not uncommon that nationally accepted versions of standards differ in details from their internationally accepted counterparts. [Ed de Moel, demoel@saltmine.radix.net]
MUMPS has better portability than C or any other language I'm aware of. The VA has successfully run the same 15000 routine system on almost every platform imaginable. VA Kernel and FileMan, the core of Decentralized Hospital Computer Program (DHCP) and CHCS (The DoD version of DHCP) and IHS (Indian Health Services) has been run, with very few changes, on machines ranging from PC's (over 80 VA Medical Centers running on 486's) to VAXen (other VA's running VMS) to Alpha AXP's (the replacement for the VAXen and some 486 sites) to IBM RS/6000's running AIX (DoD with CHCS from SAIC) . [John E. Kemker, III, kemker.j@atlanta.va.gov]
MUMPS is available for at least the following platforms:
[Jon Diamond, jdiamond@hoskyns.co.uk]
M is a full-featured procedural general-purpose programming language. SQL is a declarative language for relational database queries only, and must be embedded in a general-purpose programming language in order to achieve Turing completeness. M accesses its database at low level, almost like programming in ISAM level. SQL works on the relational level, a higher level of abstraction.
Both are procedural, interpreted applications languages. Both have a line-oriented, verb-object type syntax. M has additional features: better string handling, multidimensional string-indexed arrays, persistent variables, multitasking, multi-user support, dynamic code. M offers greater standardization and portability. Although there is an ANSI standard for BASIC, it is of little practical importance because few vendors conform to it, it is not rich enough to permit development of real-world applications within the standard, and there is a tradition of non-standard vendor extensions. The state of M standardization is superior. The Veterans' Administration, in particular, took a leadership role in writing validation suites that assure vendor conformance to the standard. Vendor choice: BASIC is currently dominated by a single company, Microsoft. There are other vendors but few have any practical importance. M is available from a wider range of vendors.
DASL (DSM Application Software Library). Based on DSM (Digital Standard M), it allows one to build database applications by defining data items and interactively designing screen placement. DASL runs on VMS and Unix platforms.
"I used to build apps with DASL... One of the things I really liked
about DASL is that it handled a lot of routine stuff, allowing me to build apps
in about 30% of the time that it would have taken with straight M coding--
which, in turn, is considerably faster than coding in most other languages :^)
Because DASL is written in M it was easy to modify to add special
features." [Aaron Seidman]
Others include:
[Jon Diamond, jdiamond@hoskyns.co.uk]
[01/95] Arthur B. Smith, ART@vets.vetmed.missouri.edu, has recently launched what is probably the first general-purpose public M FTP site. You can reach it by anonymous ftp. The location, in URL format, is: ftp://vets.vetmed.missouri.edu/mumps/ For conventional ftp access, issue the command ftp vets.vetmed.missouri.edu. The beginning of a session looks like this:
ftp vets.vetmed.missouri.edu Connected to vets.vetmed.missouri.edu Name (vets.vetmed.missouri.edu:dpbsmith): anonymous 331 Anonymous Login OK, send id as password. Password: [type in your e-mail address here] 230-User logged in 230- Welcome to the University of Missouri-Columbia Department of 230- Veterinary Medicine and Surgery FTP Server.
As of 1/95, this location appears to contain everything from the NEMUG BBS, as well as DT-STUDENT and the M FAQ. See the description of the NEMUB BGS, below. --DPBS
(All of the BBS'es listed here are in the USA. --DPBS)
There are several WWW sites that deal with MUMPS. Instead of listing them all here, we have only listed a few. These sites have references to other sites on the WWW.
In M, the current date and time is contained in a special system variable, $H (for "HOROLOG"). The format is a pair of integers separated by a comma, e.g. "54321,12345" The first number is the number of days since December 31st, 1840, i.e. day number 1 is January 1st, 1841; the second is the number of seconds since midnight. But why 1841?
According to Steve Clay, steve_clay@delphi.com, the following answer appeared in the "Just Ask!" column of the September 1993 issue of "M Computing," a publication of the M Technology Association, Silver Spring, MD 20903 (Phone: 301-431-4070), in the form of a letter from James M. Poitras:
"Starting in early 1969, our group created the Chemistry Lab application at Massachusetts General Hospital (MGH), which was the first package in the MGH MUMPS with Global Data Storage and many of the features of the language today... "When we started programming, there were no utility programs of any type. We had to write them all: time, date, verify database, global tally, print routine, etc. I ended up writing initial versions of most of these. "When I decided on specifications for the date routine, I remembered reading of the oldest (one of the oldest?) U.S. citizen, a Civil War veteran, who was 121 years old at the time. Since I wanted to be able to represent dates in a Julian-type form so that age could be easily calculated and to be able to represent any birth date in the numeric range selected, I decided that a starting date in the early 1840s would be 'safe.' Since my algorithm worked most logically when every fourth year was a leap year, the first year was taken as 1841. The zero point was then December 30, 1840... "That's the origin of December 31, 1840 or January 1, 1841. I wasn't party to the MDC negotiations, but I did explain the logic of my choice to members of the Committee."
Although the M language itself is standardized, the operating environment and utilities, alas, are not. And they are nonstandardized in the worst way: the actual functionality doesn't vary much across vendors, but the details do. Gardner Trask has provided the following guide:
Function MSM DSM MVX/MSQL DTM Utility Menu %UTL %UTL UTIL zzu Routine Directory %RD/%ROU %RD/%RDX %RD/%RDISP %rd Routine Print %RP %RS %RO %rsave Routine Change %RCHANGE %RCE %RCHANGE %rsearch Routine Compare %RCMP %RCMP %RCMP %rload Global Directory %GD/%GLO %GD %GD/%GDISP %gd Global List %GL %G %G %g Global Edit %GEDIT %GEDT %GED %gedit Global Change %GCHANGE %ZGE %GCHANGE %gedit Global Transfer %GCOPY %GC %GOQ %GIQ
[Gardner Trask, trask@world.std.com]
[In case anyone is not familiar with Scott Jones, let me say, in a offhand, understated way, that he knows what he is talking about--DPBS]
A number of people have talked about the performance/maintenance issues with comments, so I thought I'd clear things up a bit, at least for the implementations that I deal with (ISM,DTM). Double semi-colon comments are placed in-line into the object code, so it is best (from a maintenance view as well) to have a separate label for each logical section of data, followed by lines of ;; data, that is not in any path of execution. For normal comments, if they are at the end of a line that already has code on it - there is absolutely NO effect at all on performance, so comment to your hearts content. If the comment is all that is on the line, there is still a beginning of line token - which can be expensive, esp. in frequently executed loops. The reason is that the BOL token does a lot of work after every so many lines, such as allow the next process to run (on systems like DTM), or check for ^C,RESJOB, or other inter-process communication. For long runs of comments, such as the maintenance section at the top of a well written routine, if you have M/SQL (for ISM,DTM,DSM or MSM), you can simply use the macro pre-processor and bracket the code in #if 0 ... #endif. This technique totally eliminates the overhead, but it does mean that the maintenance section is not present in the M source, only in the macro source (this can be an advantage if you ship M source to customers, but don't want them to see all of your descriptions of bug fixes). Alternatively, try not to start execution on the first line, but use a label after the comment section. (i.e. DO entry^foobar instead of DO ^foobar) [Scott P. Jones, scott@INTERSYS.COM]
The MUMPS Development Committee (MDC) is responsible for defining the M Standard. Unlike other language standards bodies (such as ANSI and ISO), the MDC is dominated by users - systems developers, rather than implementors. Anyone with an interest in the M language can join the MDC and all members have a single vote. MTA-North America acts as the MDC Secretariat and publishes all documents pertaining to ANSI X11.1, including the Standard, bindings specifications (for example, X Windows, SQL and GKS) and MDC proceedings. There are also counterparts to the MDC in Europe, Brazil and Japan (MDCCs) which feed in non-US contributions and have voting rights at the MDC. [Jon Diamond, jdiamond@hoskyns.co.uk]
Answering complex questions is one of the biggest reasons we invest in the time and expense of using a database management system. Several types of graphical products exist today to help you query your database. Of these, dedicated front-end query and reporting tools such as Borland ReportSmith for Windows and Intersolve Q+E are probably the best-known in corporate environments. Such tools are typically client applications designed to query data from corporate databases residing on client servers. Typically, these products have no built-in data-management capabilities; many require you to have a detailed knowledge of your database and the workings of relational databases in general.
PC-based database management systems let you construct queries and produce reports. You need a fair amount of database savvy to construct a query that produces the right result. Fortunately, the products are getting better at making this process easier. The two leading PC-based database management systems are Microsoft Access 2.0 and Borland Paradox for Windows 5.0.
A query is a request for information from a database. Methods for specifying a query have improved over time. Traditionally, one would have used SQL, or structured query language. In the late 1970s, IBM Research developed a new query technique called QBE, or query by example. In QBE, one supplies query details by filling in a table with values. For instance, to locate rows where the state value is New York, one would move to the State column and enter NY. To find salaries greater than $40000, one would enter > 40000. The basic idea of QBE is to make the dialogue easy to learn and reduce any reliance on keywords or language syntax.
It is possible to set up a database in M using a tool such as the VA Fileman package. Reports can be generated by means of the Report Writer feature of VA Fileman. Related records in a database are organized together to form a file, or in MUMPS terms a global. A field is a unique observation or data element. A record is comprised of one or more fields, a file (or global in M) is a collection of records and a database is the collection of all files comprising an application. [ Jeff Loeb (loeb@san-diego.va.gov) ]
As told in a series of e-mail exchanges in comp.lang.mumps in Sept/Oct 1996. Accuracy is not insured.
From: Monika Kratzmann (monika@INTERSYS.COM)
We are looking for some historical information on the evolution of M to be
published in an article. It seems natural to turn to the members of this
newsgroup inviting you to provide any information on this you may have. Your
consideration in providing us with your knowledge about the history of M is
deeply appreciated. Thank you one and all.
Monika Kratzmann
InterSystems Corporation
"Ellis A. Bauman, 608-829-5334" (ellis.bauman@AUP.WISC.EDU)
It's not clear what specific kinds of info you're looking for, but here's a
brief note on the beginnings, at least as far as I recall: The language was
developed at Massachusetts General Hospital in a lab run by Dr. Octo Barnett.
It was developed with federal grant money --- hence was in the public domain,
and the name MUMPS stems from Massachusetts General Hospital Utility
Multi-Programming System
Among the chief developers was Neil Pappilardo who later left Mass Gen, and started Meditech, adding some proprietary features to MUMPS and calling the result MIIS (Meditech Interactive Information System) --- marketing medical records systems to hospitals, clinics, medical labs,etc.
At Mass Gen, the language was used to deal with clinical medical data --- hence its strengths in string handling (lots of text data), sparse arrays (not every patient undergoes every possible lab test), and other such features. The original platform was (at least I think it was) a PDP-15. It was later ported to the PDP-11 and other similar "minis" such as the Data General machines like Novas and Eclipses. As the idea spread among other medical researchers, people began adding other features, and there soon developed a whole bunch of "dialects" which frustrated the researchers because they couldn't exchange software very easily. To solve that problem, the MUMPS Users' Group was formed and efforts to standardize the language began. Dr. Barnett was among those who was most forceful in arguing for the creation of MUG and the standardization effort. I do not remember who first proposed that ANSI approval be pursued. The current MTA organization is what MUG has evolved into, via the name change. I believe Joan Zimmerman was the first MUG staff member, and she wrote (or edited?) some of the first MUMPS tutorial materials published by MUG. There is probably lots more material, and details, available from the MTA "archives", and other people who were involved in those early days. Perhaps some of the other newsgroup members will know how to contact some of the people I've mentioned. For example, there is a short history in Chapter 1 of "The Complete MUMPS" by John Lefkowitz. There are also some historical notes in the MUMPS FAQ (for example, "What happened in 1841?"). I hope the above is both accurate and helpful.
From: rodd@panix.com (Rod Dorman)
As I recall it, the original platform was the PDP-9.
From: Lev Jacob (lev@TRENDLINE.CO.IL)
I think the original plarform was a PDP-8. When the language was adopted by DEC
it was a stand-alone OS called MUMPS-11 on PDP's. I can't remember MUMPS for
Novas but I can remember MUMPS for Tandem Main Frames with a Multi-Cpu built in
functionality. Good luck. Jacob Lev.
From: Dennis J Brevik (dbrevik@ix.netcom.com)
The original platform was a PDP-9. When the MGH version was picked up by DEC it
was productized onto the PDP-15. A couple years later it was rewritten by DEC
for the PDP-11. The systems were standalone. The date that DEC officially
picked up a magtape of MUMPS (PDP-9) from LCS at MGH was October 3, 1970. It
was a pleasant fall day. The PDP-15 MUMPS system was installed at its first
site (Health Data Management Systems of Denver) in May 1971. It took two hours
to install, amazing everybody on the site, who were expecting a week or two
effort.
Dr. Octo Barnett was in charge at the Laboratory of Computer Science at MGH. Neil Papalardo and Bob Greenes were major contributors. Neil went on to form Medical Information Technology (Meditech), Greenes was a medical doctor as well as holding a PhD in computer science - both degrees awarded simultaneously from Harvard. Bob went on to be President of Automated Health Systems of Wakefield MA and Burlingame CA.
In a Boston meeting in Fall 1972 Bruce Waxman of NIH told the audience in no
uncertain terms that if they wanted to get NIH money for their computer
projects they damned well better be using MUMPS, that NIH was not interested in
reinventing THAT wheel, thank you. MUMPS took off. I was the original product
line and technical leader on MUMPS-15 at DEC. Paul Stylos was the technical
leader for MUMPS-11. Evelyn Dow was the original Marketing representative. And
let us not forget Dave Ensor of Scotland, who made significant technical
contributions. The DEC executive who originally saw the value in MUMPS was Stan
Olsen. Sam Moulton was also on the technical side.
Respecfully, Dan Brevik
From: "Ellis A. Bauman, 608-829-5334" (ellis.bauman@AUP.WISC.EDU)
Well, Jacob, all I can say is that when I first encountered MUMPS (in the early
to mid 1970s), it was MIIS on a PDP-15, and I later worked on a Data General
machine, also MIIS. Both of those were stand-alone systems, dedicated to MUMPS
(or at least a MUMPS-like, derivative, language).
From: dpbsmith@world.std.com
(Daniel P. B. Smith)
Hi, Monika... There is a 16-page article, "History of the Development of
Medical Information Systems at the Laboratory of Computer Science at
Massachusetts General Hospital" by G. Octo Barnett, MD, in "A History
of Medical Informatics," edited by Bruce I Blum and Karen Duncan,
published by the ACM Press (Addison-Wesley), 1990, ISBN 0-201-50128-7. I bought
it on sale for five bucks at Quantum. It's almost certainly out of print but it
couldn't hurt to ask Quantum if they have any more copies kicking around.
According to the article, the first implementation, of a language called MUMPS, by Neil Pappalardo, was on a PDP-7. Not a PDP-15 or a PDP-9, a PDP-7. He traces its origins from JOSS through BBN's Telecomp and StringComp. Richard Walters' "An ABC of MUMPS" contains a "Brief History of MUMPS" on pp. 20-22 with a family tree showing the root in Rand Corporation JOSS, through BBN JOSS, via TELCOMP and STRINGCOMP to MGH MUMPS. -- Daniel P. B. Smith dpbsmith@world.std.com
From: Etienne Cherdlu (gz64@cityscape.co.uk)
Now this brings back some memories. I remember using TELCOMP back in 1969 (27
years ago). We used it, via a dial up line, on a PDP-7 (TELCOMP II) and later
on a PDP-10 (TELCOMP III). I don't remember much about the machines that we
used other than that we leased time from a company called Time Sharing Limited
of Great Portland Street, London. I also have a note from that time about
on-line storage charges. It cost 30p (about 45 cents) per 640 byte block per
month! The family resemblance between TELCOMP and M is just about recognizable
especially if you were familiar with MUMPS-11. The following is a fragment of
TELCOMP code that was written on 12 December 1971:
1.04 TYPE #,"ENTER ONE OF THE FOLLOWING:-";MENU 1.05 TYPE FORM X FOR X=1:1:4 FOR END=10^15 1.06 READ GRNO IN FORM 15 1.065 DONE IF GRNO=END 1.07 TO STEP 1.06 IF GRNO>4 1.08 TO PART GRNO+1 2.01 DO PART 50 2.02 READ N,K 2.03 DO PART 51 2.04 TO PART 15 .. 15.01 LINE FOR X=1:1:3 15.02 TYPE MINPL,MAXPL IN FORM 17 15.03 TYPE FORM 17 15.04 DO PART GRNO+15 FOR X=MNPL:STPL:MXPL 16.01 Y=(X^N)+K 16.02 Y1[X]=(((Y-MNPL)/(MXPL-MNPL))*2)-1 .. FORM 15 ITEM NUMBER? ##### FORM 17 MINIMUM ##### MAXIMUM ######
Comparison with M:
Clearly some of the origins of M can be seen in TEL 7) DCOMP. Does anyone
know where the idea for globals originated? What elements did other languages,
such as JOSS bring to M?
Regards Etienne Cherdlu
From: Jon Diamond (jon.diamond@capgemini.co.uk)
This takes me back too! Oh for the good old days - when programmers were really
programmers, disks were 2.5Mb in size and part numbers ranged from 0.01 to
327.67 (or some such obvious number)!!!! Well, the comment is not totally
accurate - line numbers only had 2 decimal places if you're being really picky.
BTW I used to know magic numbers - 84, 84*84 84*84*84 etc FWIW. I've now
forgotten what they were, but I'm sure some of you MUMPS-11 people must
remember? I do know why I needed to know them, but that's another story... --
Jon Diamond, Cap Gemini UK Go Proverb: "On the second line 6 die, 8
live"
The first thing to be aware of is "arrays" as they work in other languages: when you have a "set" of components (like the states in the USA) you want to use a method of reference that allows you to manipulate the "set" as a unit when that is convenient, and its members when you are dealing with the properties of the individual members of that set. Now, in languages like Pascal and C, you would create an array with 50 members, and you would build a table:
State[0] = (pointer to string) "Alabama" State[1] = "Alaska" ... State[49] = "Wyoming"
and probably some associated tables:
Capital[0] = "Montgomery"; Abbrev[0] = "AL"; Capital[1] = "Juneau"; Abbrev[1] = "AK"; ... Capital[49] = "Cheyenne"; Abbrev[49] = "WY";
If you want to loop through these arrays, you don't need any special functions: there are 50 elements in each, and "for i=0 to 49" or for (i=0; i < 50; i++) will do just fine. In M[UMPS], arrays can be done in the same fashion, in which case For i=0:1:49 would do just fine to loop through all states, but it is much more common to use a different method of indexing the array(s), using a string as an index. You could store the array as:
State["AL"] = "Alabama/Montgomery" State["AK"] = "Alaska/Juneau" ... State["WY"] = "Wyoming/Cheyenne"
(or, if your method of usage would make that more convenient you could use State["Alaska"]="AK/Juneau" State["Juneau"]="AK/Alaska" for that matter). However you "index" the array, the addressing will not be as simple and straightforward as in traditional languages:
Or, a simple loop across all states would look like:
Set index="" For Set index=$order(State(index)) Quit:index="" do...
The function $order looks at this internal table, and tells you what the next index is after the one that you specify.
So... At the first call, the specified index is "" (empty string), and $order will look for the first entry in the table. Currently this is "AK". After "AK", $order would find "AL", "AR", "AZ", etcetera, up to "WY". When called with the "last" index ("WY"), $order would return the value "" (empty string) to signal that it could find no more members.
Now, that seems fair for an array like this, and we'll always have the same 50 members, and always find the same ones in the same order, so why go through all this bother? Well, that will become clear when you're dealing with sets that are more dynamic in nature. Suppose that Good Old Fidel finally steps down and Cuba requests membership as a state, there would be a storm of protests, but let's assume that the request would be approved. In most other languages, we would have to do a lot of recoding to insert Cuba in the "proper" place in the new array of states. In M[UMPS], all we have to do is Set State("CU")="Cuba/Havana"
$order(State("CT")) currently returns "DE", but after this insertion, it would suddenly return "CU", and $order(State("CU")) would return "DE": by the way of indexing that M[UMPS] does for you "behind the scenes", indexes are always stored in alphabetic order, and you won't have to worry where things are, or how to get them into the proper sequence.
Of course, this is where it starts to matter what value you use for an index:
In this example, I also used another "idiosyncracy" of M[UMPS]: I stored "State/Capital" into one single value. You would use the function $Piece to separate out these values. Whether you would use a set-up like I depicted above, or
State(abbreviation,"Cap")=capital State(abbreviation,"Name")=name
is up to the needs of your application.
Of course (and I don't want to say that M[UMPS] is an object oriented language, it's 30 years old now, and definitely showing its age), this is a feature that you see a lot nowadays in object oriented programming as well: you pass the complete object, and leave it to the recipient-software to figure out which properties of the object are interesting to it. [Ed de Moel]
A lively debate concerning M as a first language for non computer types had varied and interesting opinions. Here are some of them;
-- From: Paul Perrin I think M is a *perfect* language to learn about fundamental programming principles. Software engineering can come later - and is abusable in any language. A computer handles three types of execution - sequential, conditional and iterative. Each type can be demonstrated (and learned) in M with _no_ messing about - no 'declarations', no 'introductions', no 'directives', no compiling etc... Experienced programmers _forget_ how they learned to program - Ken Knecht's 1979 definition of a string in 'Microsoft Basic' from the dilithium Press as 'a group of alphanumeric characters surrounded by double quotes' left me blank for weeks - what did he mean by group? Character mode M is (at least) as good as the original 'basic's were for discovering what computers can 'decide' and 'think' and 'store'. Don't listen to the experts -- they forget from whence they came. Show him M (and follow up with Java). Regards Paul Perrin -- From: fbdennis@mindspring.com (Floyd Dennis) Paul Perrin wrote: >I think M is a *perfect* language to learn about fundamental programming principles. For some reason, it surprises me that I tend to agree. <g> Before a "beginner" can even begin to grasp such things as "structured programming", "top-down", etc., they have to get a good feel for the basics. Things like Control, ALU, I/O, and Storage. M brings you a lot closer to the basics than many higher(?)-level languages. Also - for educational purposes, interpreted languages are great. Nothing is going to give a better instant gratification kick than being able to type a command directly and get an immediate answer. <g> ><snip> >Show him M (and follow up with Java). > *THAT* will send him running back to M in a hurry. :) Floyd Dennis