
The Mumps Programming Language - mabynogy
http://www.cs.uni.edu/~okane/
======
seibelj
There is a company called MediTech in Massachusetts that uses a derivative
language of MUMPS called Magic. I know several programmers that have worked
there. There are thousands of engineers writing in this language as we speak.

From what I can remember:

-Only global variables

-Variables must only be capital letters, maximum length 6. If you run out of variables, you must cleverly use them in a routine and set them back to what they are. This means you can't use a name like myVar - you use AAAFD, ZBVCXZ, etc.

-System functions are usually things like ., >, ', ], so code looks like .'AAAF]{\;:..

-Meditech writes all of their own languages, databases, operating systems, tools, etc. You can only write in a non-Meditech language if you get approval from a multi-tiered architectural design board, which barely ever happens

-The founder hated C with undying passion. No one is ever allowed to use C

-All programming hires go through a 6 to 12 month training process to learn the tools, languages, and systems. As they almost exclusively hire non-CS majors, such as math and physics majors, they don't typically have a programming background and don't realize how bizarre the MediTech stack is

Because MediTech engineers get experience in a proprietary suite of
technologies that is only used there, it is extremely difficult for them to
get new jobs at the same pay grade and experience level. 5 years at MediTech
is worth 0 years anywhere else. However, I have hired a few of these people,
and while they knew nothing about say Python, JS, Linux, etc. when hired,
their deep understanding of how computers work made them very skilled once
they picked up the modern technologies. Not many engineers program for years
in low-level nightmare languages before touching JavaScript or Python, most
start high-level and go lower. The foundation provided by working in a
language like Magic makes them know computers at a deeper level than most.

~~~
arielweisberg
I interviewed at MediTech while I was in college. During the interview I
pointed out the issue of how working on proprietary technologies would have an
impact on my career. This along with the fact that the compensation they were
offering was significantly less than what I was offered as an intern at
Goldman Sachs and another company no one would know.

I swear it was something insane like 36k a year in 2005. compared to 55k for
GS . I asked them if it came with something to offset that like a pension or
housing and they looked at me like I was crazy. I asked them to explain what
they had to offer me and they made some stuff up about it being a great job
with advancement potential. I think the word loyalty may have come up.

I didn't get an offer not that I would have said yes.

The lobby was nice as I recall. Lot's of open space, granite, and flowing
water. Maybe that makes it worthwhile? Oh and you have to wear dress clothes.
On 36k a year.

~~~
dhekir
Is 36k that insane? That's the average starting salary of French engineers and
some PhD-level researchers from relatively well-ranked universities. 1/3 of
which are compulsory taxes (not including income tax), so in the end it's
about 25k of net disposable income per year.

~~~
digitalzombie
It is insane. I started at the bottom of recession 2009 at a university for
46k.

I'm sure it depends on geography and living cost but 36k is very low imo for a
private company.

Public companies such as public university, government, and such still pay a
bit above that on top of good compensations (healthcare, vacations, etc...).

This is USA of course.

France in general could be different in term of tax, healthcare, etc...

------
z3ugma
Unpopular opinion: I actually really like working in MUMPS, which is now just
called M. I develop in M every day.

There are modern ANSI standards for the language, and several private vendors
and open source implementations.

There are 2 things I like about M:

1\. It has limited commands and is whitespace-aware \- Newer developers can
jump right into M, precisely because it lacks higher-level abstractions like
first-class functions or closures. It's easy to memorize the standard library
and easy to read code (because it's whitespace sensitive like Python).

2\. The NoSQL database built right into the code \- You access the built-in,
persistent database the same way you access regular data structures. When
setting values into an array you do something like "set foo(bar)=1". In order
to persist that same data to disk, you just do set ^foo(bar)=1. This means
less worrying about query languages and ORMs.

The database is a sparse B-tree structure so it's wicked fast at reads and
writes. Great for a fast key-value store. There are people using M's battle-
hardened NoSQL database with Node.js drivers, and you're very unlikely to find
a bug because it's been in production so long. This makes it good for mission-
critical applications like healthcare and finance.

Check out Rob Tweed's work with M:
[https://robtweed.wordpress.com/2012/10/24/i-have-seen-the-
fu...](https://robtweed.wordpress.com/2012/10/24/i-have-seen-the-future-and-
its-node-js-shaped/)

~~~
jacquesm
> Unpopular opinion: I actually really like working in MUMPS, which is now
> just called M. I develop in M every day.

I know people that love working in COBOL. For the most part that is because it
is what they know. Do you have extensive experience with other
platforms/languages? How do you rate them side-by-side?

> and you're very unlikely to find a bug because it's been in production so
> long.

This goes for anything that's old. But that does not equate to 'good', it's
just old. Just like new isn't necessarily better old isn't either.

And there are usually plenty of bugs in those codebases, just not in the
runtime. But the user supplied code usually pre-dates any kind of automated
(or even at all) testing other than 'try stuff and see if it produces the
right results'.

The MUMPS codebase I worked on in the 80's was so fragile that deleting a
single global string could cause the whole system to break down in ways that
required a restore from backups. Don't ask me how I know that ;)

~~~
nobodyorother
I'll second that unpopular opinion and claim I have experience with many other
languages that I also enjoy.

The fun part about Mumps is that it's basically Lisp's ugly sibling, without
meaningful scoping rules. You can easily do lots of terrible things in Mumps,
but those things are usually more straightforward than the terrible things you
do in other languages. You can also do elegant things, though a little less
straightforwardly.

My single biggest complaint about Mumps codebases is that they're usually old,
which means they have shitty documentation. Not that new ones are necessarily
any better, but at least there's a chance new things are written in Orgmode or
something :)

~~~
jacquesm
I've yet to see a MUMPS code base that would qualify as 'elegant', do you have
any pointers?

I'd love to see how it should be done, the only things I've seen are examples
of how things (any things!) really should not be done.

~~~
mabynogy
[https://github.com/robtweed/EWD/tree/master/m_apache](https://github.com/robtweed/EWD/tree/master/m_apache)

~~~
raverbashing
This mess makes perl look readable

Thanks for proving without a doubt that Mumps belongs in the trash can

~~~
jacquesm
You probably won't believe it but this is actually very clean MUMPS code. If
that's the shining example then you now have a bit of a glimpse of what the
bad stuff looks like.

------
rnprince
I used to work at Epic, where this language is used to implement much of the
leading healthcare system in the United States. Many people there encouraged
me to refer to it by different names like "M," "InterSystems Caché," "Caché,"
or even to my surprise "C."

I'm very, very happy to not be using this language anymore. After my first
year on the job, I read some JavaScript code, and I nearly wept at how
comparatively beautiful it was.

~~~
ajmurmann
Why did they encourage you to refer to it by different names? In what context?

~~~
amptorn
"Mumps" is a pretty awful name to use for the purposes of healthcare software.
You might as well call your database system "Cancer".

------
jacquesm
Mumps is everything a programming language should aspire _not_ to be. It's
worse than RPG, worse than MAPPER, worse than MIMER and all of those put
together.

If a job description contains the word 'Mumps' and it is not in a sentence
about your medical history: run like hell unless you are starving.

Source: was a Mumps programmer long long ago in a short stint at a bank that
fortunately got bought out by another bank which had saner ideas about
automation.

------
rmsaksida
Obscure Mumps trivia: in the 80s, it was fashionable for the Brazilian
Judiciary to build systems in M. (I have no idea why). Many courthouses and
tribunals in Brazil are backed by large Mumps-based systems, not just for
courthouse stuff but also HR and other purposes.

I worked as a civil servant in such a tribunal. Mumps was the first
programming language I used professionally - in 2009! I wrote M for a living
for around a year. It's still being heavily used in the place I worked at. My
colleagues, who were more senior than I by a few decades, had written hundreds
of thousands (millions?) of LOC in Mumps and developed a rich ecosystem of
internal tools and libraries for it. It was a bit scary to do maintenance work
on code that was written in the 80s, but I could often look at the author's
signature and find out he was sitting right beside me - still pumping out
Mumps. :-)

I can't say I loved the language, but it has some interesting concepts and
reading about it makes me feel nostalgic.

Something weird about Mumps that I didn't see others mentioning here is how
common it is for M programmers to abbreviate commands. Every command in Mumps
can be abbreviated; "w" for "write", "i" for "if"; "s" for "set" and so on.
This causes code to be extremely terse, and hard to understand for a beginner.
A very simple example:

> I ($G(^ATM(1000))+$G(^ATM(500))+$G(^ATM(100)))<=0 D

> . W #,!,"There is no money available in this Machine. Sorry for the
> inconvenience."

> . Q

It gets way more complicated than that. After reading this kind of code for a
few months, you get really good at parsing it.

~~~
otoburb
>>It gets way more complicated than that. After reading this kind of code for
a few months, you get really good at parsing it.

This must be how APL language users feel parsing their ultra-terse syntaxes
(includes J/K/Q variants). Seems most applicable to quant shops that still use
kdb+.

------
doughj3
This page mentions the EHR used by the U.S. Department of Veterans Affairs,
known as VistA[0], developed using MUMPS.

Interestingly, the source code for VistA has been obtained via FOIA requests
and so the code is available in the public domain[1]. There are now forks of
VistA, like OpenVista.

At one point we had to argue with Github to support syntax highlighting for
M/MUMPS:
[https://github.com/github/linguist/pull/148](https://github.com/github/linguist/pull/148)

[0] [https://en.wikipedia.org/wiki/VistA](https://en.wikipedia.org/wiki/VistA)
[1] [https://en.wikipedia.org/wiki/VistA#Usage_in_non-
governmenta...](https://en.wikipedia.org/wiki/VistA#Usage_in_non-
governmental_hospitals)

~~~
epmatsw
There's a docker image floating around somewhere out there that gets a VistA
install up and running.

~~~
thomasjudge
Has anyone tried this? Played with this? Is this a viable EMR system for an
org that doesn't have a lot of money? Like for support either?

------
comice
I worked at a company that used Mumps. They used some super-old interpreter
that had a pretty low limit on the code size.

The actual size of the source code.

As the codebase grew, they had to shrink down the code to be able to fit it
all in. Comments were the first to go. The end result was single letter
variable and function names. The code was impenetrable!

Presumably this is no longer a limitation :)

~~~
detaro
Reminds me of how V8 used the length of a function's source code as a
heuristic to decide if it should be inlined or not -> adding comments could
slow down your JS. But of course JS already had code minifiers.

------
tempodox
I took a look at the “Code examples from the book”. I haven't, ever, seen a
nightmare like this.

Just one snippet from the User's Guide:

    
    
      If you use a goto command, all do command pending returns
      are canceled. That is if you invoke a section of code by
      means of a do and the section of code executes a goto
      command, the return to the line the do was on is canceled
      as well as any other pending returns.
    

Even BASIC does better than that.

~~~
jacquesm
That's because they drop the stack.

Yes, basic did better than that _but_ you can actually 'goto' into some line
in another subroutine in BASIC which can cause all kinds of interesting
results (usually not the ones you intended though).

~~~
tormeh
You can do the same with longjmp in C. You jump onto an empty stack, so you
only have global variables to work with. It's fascinating, but not recommended
:)

------
tsomctl
[http://thedailywtf.com/articles/A_Case_of_the_MUMPS](http://thedailywtf.com/articles/A_Case_of_the_MUMPS)

~~~
mcknz
beat me to it...

[http://thedailywtf.com/articles/MUMPS-
Madness](http://thedailywtf.com/articles/MUMPS-Madness)

[http://thedailywtf.com/articles/Revenge-of-MUMPS-
Madness](http://thedailywtf.com/articles/Revenge-of-MUMPS-Madness)!

~~~
clock_tower
I, too, have googled MUMPS.

~~~
mcknz
I read the DailyWTF article on MUMPS when it was originally posted, so that
prompted me to go look for it.

~~~
clock_tower
My comment was aimed more at tsomctl and moomin than at you, to be honest. Say
"MUMPS" and people will fall over themselves to cite The Daily WTF, as if it
were all there was to be said on the matter.

~~~
tsomctl
I, too, read the Daily WTF when that article first came out (in middle school!
Time flies.) Although, to be honest, it was a lot funnier then than it is now.

------
nwhatt
Ex-Epic developer here.

MUMPS is older than SQL, so preSQL might be more appropriate than NoSQL.

There were moments of joy programming M, and the performance, scalability, and
HA aspects of the Intersystems implementation don't hurt Epic one bit in the
sales process.

At Epic, there are so many abstractions away from M that you might start to
think you're working in another language. You never set globals in production
code, instead using Epic's homegrown ORM to define schemas for your data.

At the end of the day, lack of first order functions and any other data
structure other than the B-tree array makes for fun problem solving, but not
necessarily clean and concise code.

~~~
__float
It's funny, this is the first I've heard of Chronicles being called an ORM. I
wouldn't really hesitate to call it a full database itself, written in M. But
now that I think about it, I think you're quite on point there.

(You're telling me though you never came across "end-user" API-level code that
was directly digging around in ^ER, ^ER1? Hahah)

~~~
nwhatt
Yeah smart people work at Epic, and smart people with ties to the midwest end
up staying longer than 5-6 years. Epic does get a lot of things right,
especially the code review process. If someone saw a reference to ^ER in code
being committed, you can bet that it would get changed. The linter (HXPARSE)
would actually prevent you from moving code with certain global references.

------
sixdimensional
One fun fact: MUMPS had an early "NoSQL" precursor key-value storage engine
(the "M" database), that could be directly accessed as if it were a global
variable.

"The M database is a key-value database engine optimized for high-throughput
transaction processing. As such it is in the class of "schema-less", "schema-
free," or NoSQL databases. Internally, M stores data in multidimensional
hierarchical sparse arrays (also known as key-value nodes, sub-trees, or
associative memory). Each array may have up to 32 subscripts, or dimensions. A
scalar can be thought of as an array element with zero subscripts. Nodes with
varying numbers of subscripts (including one node with no subscripts) can
freely co-exist in the same array." [1]

I had to work with MUMPS once in the past when I was working in the green-
screen world in healthcare. I also had to work with Pick/D3 and Basic. It was
kind of nice to start there, then move to relational databases, and then see
the world get excited again in older models of databases with the NoSQL
movement (albeit, much more scalable and distributed).

[1] [https://en.wikipedia.org/wiki/MUMPS](https://en.wikipedia.org/wiki/MUMPS)

~~~
rnprince
Yeah, MUMPS was pretty prescient in this way. As someone who's experienced the
changes first-hand, what do you feel are the most important NoSQL developments
since MUMPS?

Do you have a preference on NoSQL vs relational databases?

~~~
sixdimensional
Well, this is my opinion.

The latest generation of NoSQL databases really tried to add to the
distributed / scalability story of databases, as well as provide simpler
"input", "output" and "storage mechanisms". This, often at the cost of a
degree of ease of use of query languages to be able to easily analyze data.

As NoSQL movement started to come into focus, folks saw that the then dominant
traditional relational / ACID model was not scaling to internet scale (too
many JOINs, too hard to do ACID at that size or not needed, etc.). In reaction
to "internet scale", the search turned to finding new or innovative
alternatives to the relational model (which really, just represented what was
the state of the art at the time). This is how we got BASE instead of ACID,
and went back to key-value.. or document-oriented.. or graph-based... or
Hadoop/Map-Reduce, etc. People exploring lots of alternatives.

I think people mentally "threw relational databases out" for a while as
quickly as they threw out the other alternatives (the precursors to relational
databases), when relational databases came along. Many have found it hard to
live without relational databases.

I think modern NoSQL databases try to maximize on input/output/storage and
distribution / MPP of data. By now, they give some more expressiveness for
query (like MongoDB, Cassandra, Hive/Impala in the Hadoop world), although SQL
still beats them in my opinion for ease of use. SQL also could have advanced
as the query interface for those systems too, and if you look at the SQL:2011
standard, you'll see that it included methods for querying things that are
distinctly "non-relational" (multivalue fields, etc.).

NoSQL databases also more cleanly map to object models, the dominant
programming paradigm (although who knows, maybe one day that too shall
change).

No, I don't have a preference of NoSQL vs relational databases in general. I
believe they are complementary and maybe there isn't such a thing as a general
purpose database for every use case. I do believe in the old saying, "try to
use the right tool for the job". There are cases when a NoSQL database works
superbly, and others where a relational database just feels right. For
example, storing "objects" quickly works well with a NoSQL database vs.
querying for a denormalized data warehouse seems to fit well into a relational
database (ironically of course, since they are often denormalized and not
third-normal-form 3NF).

Anyway, that's my take... but anyone else who has input should feel free to
chime in.

~~~
sjg007
I've been reading more on datalog, it seems to be a better way for data
handling.

------
kdtop
I work with M/MUMPS on a daily basis. It's no surprise that it is a primitive
language, as it was developed in 1966 to run on PDP-7 computers, less powerful
than a raspberry pi. But M is still very relevant today because it is the
power behind many (most?) of the electronic medical health record (EHR)
systems in the world: Epic, Meditech, VistA (from the VA), Allscripts (more
here:
[https://en.wikipedia.org/wiki/MUMPS#Current_users_of_MUMPS_a...](https://en.wikipedia.org/wiki/MUMPS#Current_users_of_MUMPS_applications)).
Note that it is also extensively used in the banking industry. I have heard it
said that at least 50% of people have their money run through a Mumps
financial system during electronic fund transfers. Mumps is very fast and very
stable, IMHO because of it's lack of bells and whistles. GT.M's version of
Mumps is serious about it's moto of "Rock Solid. Lightning fast".
([https://www.osehra.org/content/fis-gtm](https://www.osehra.org/content/fis-
gtm)).

The most important part about any computing system/language is the resulting
application. Yes, it is nicer for programmers when they have advanced language
features. But ultimately, the test of how "good" a language is should really
be about how useful it is, and how widely it is used.

The wheel is very old technology and yet still very important.

~~~
DanielFallon
lol... Last time I checked GT.M was way behind lightning fast by comparison to
Intersystems' implementation

~~~
dahakon
If you put the money you save on Cache licenses toward better hardware, GT.M
will be faster. Cache would still be necessary only for the most demanding
cases.

------
drallison
MUMPS (the programming language not the disease) found a niche in the medical
world where it was developed. The name is an acronym for Massachusetts General
Hospital Utility Multi-Programming System where it was developed. There is an
ANSI standard for the language: see
[http://71.174.62.16/Demo/AnnoStd](http://71.174.62.16/Demo/AnnoStd), for
example.

I worked with the MUMPS Standard Committee trying make the language better
while simultaneously trying to minimize the problems moving the large base of
existing code to the new Standard MUMPS. MUMPS was filled with hidden gotchas.
For example, in some early versions, trailing blanks in statements were
significant.

The Wikipedia MUMPS article
([https://en.wikipedia.org/wiki/MUMPS](https://en.wikipedia.org/wiki/MUMPS))
provides some insight into the language and its genesis. The inclusion of a
key-value store embedded into the language was a significant innovation and
helped the language to be successful.

------
cartothemax
Never thought I would see a professor from my alma mater show up on the front
page of HN! I could have maybe seen Dr. Wallingford
([http://www.cs.uni.edu/~wallingf/](http://www.cs.uni.edu/~wallingf/)) for his
love of functional programming or Dr. McCormick
([http://www.cs.uni.edu/~mccormic/](http://www.cs.uni.edu/~mccormic/)) for
contributions to ADA, but not Dr. O'Kane!

Took Database Systems from Dr. O'Kane. He was a pretty fun professor.

------
robtweed
My name has been mentioned a couple of times, so let me give my take.

Forget the Mumps language which always ends up being criticised for all manner
of reasons, as witnessed here already.

Check out the database, however - it's the hidden treasure, which sadly gets
overlooked and dismissed because of conflation with the Mumps language and its
poisonous baggage.

You don't need the Mumps language to access the database. My work with it
these days is in JavaScript/Node.js, using it purely as a multi-model NoSQL
database, accessed in-process.

Check out what can be done with it here:
[http://ec2.mgateway.com/ewd/ws/training.html](http://ec2.mgateway.com/ewd/ws/training.html)

In particular check out the multi-model capabilities of the database and the
JavaScript-orientated abstractions that are possible - see parts 17 - 27.

Some may also find this interesting: [https://github.com/robtweed/ewd-redis-
globals](https://github.com/robtweed/ewd-redis-globals)

------
mdekkers
A friend of mine wrote in MUMPS, banking terminal applications. greenscreens,
that kind of stuff. He hated it, but he told me then it was a job for life, he
got paid well (not many people with those skills) and didn't really have a lot
in the way of stress....

~~~
tluyben2
I used to do a lot of work in dBase & Clipper and because of that I got
projects in other 'language integrated databases'(?) like DataEase, MUMPS,
Cache as well as Access, Foxpro and Informix. Besides Access (I guess?) these
are mostly jobs for life without stress. I still get requests and it has been
15-20 years since I touched most of those.

~~~
int_19h
How many FoxPro jobs are still around?

~~~
tluyben2
Not sure, but many. These are usually not very well advertised in my
experience as the people who still can do this are known and/or advertise
themselves to wanting to do that work.

------
moomin
The Daily WTF has a number of MUMPS-related articles. This one is good for the
basics:
[http://thedailywtf.com/articles/A_Case_of_the_MUMPS](http://thedailywtf.com/articles/A_Case_of_the_MUMPS)

------
briffle
I know at least one of the two top major EHR systems uses MUMPS (Epic
Software) at its core. If your a member of Kaiser Permanente, or hundreds and
hundreds of other hospitals/medical systems, you rely on it for your medical
records..

</shudder>

~~~
logfromblammo
I worked at Epic for a bit more than 2 years.

It was about 3 years too long. Yes, that math is correct.

As far as I recall, MUMPS is essentially the dedicated coding language for a
b-tree based database, and the only reason to ever use it for anything is for
processing huge numbers of transactions through your NoSQL database every
second, forever. I guess you also might want it if none of your employees knew
how to correctly normalize a relational database.

Other than the nightmarish accumulation of technical debt continually rolled
over since 1979, and the ungodly high turnover of people jumping ship after
realizing MUMPS was a golden ball-and-chain, it was a pretty nice place to
work. But management had a culture that it needed to force down everyone's
throats, and the tech stack was a real resume killer. I still get contacted by
recruiters desperate for MUMPS developers, and they make me feel like someone
trapped inside a house besieged by zombies. I get really quiet, and hope they
don't break any windows.

It only works because they throw a huge amount of money at it, and no one has
any incentive to cheap out on medical management software.

~~~
fivre
EPIC management's (at every level) embrace of M and all things old as holy and
glorious was what turned me off of it most. I could somewhat understand the
need to keep working with cold in an old, bad language because it was still
printing money (most anything related to healthcare does). I could not
understand that consideration any possibility of modernizing the codebase was
completely off the table--there were no R&D teams looking at new developments
in database design as possible improvements, even though the tech most in
fashion at the time (NoSQL) had striking similarities to M's own database
structure. All effort was spent towards squeezing every last ounce of blood
from ossified technology. This persisted well outside MUMPS itself: I was in
the server management division, which was a champion of AIX and HP/UX (and in
the weirder corners, VMS) over Linux. When I left there were a few people
warming to the idea that RedHat might be enterprise-y enough to serve as a
base for running M databases, but general sentiment was that most customers
would continue to use old school _nixes well into the future. Much of our time
was spent painstakingly guiding rural hospital sysadmins through manual
configuration of every sysctl and OS parameter needed to make Cache happy.
Configuration management would have reduced this to about 3 minutes of tossing
a Chef /Puppet/Salt/whatever config at a server, but was considered anathema
because it was necessary to have that special human touch involved in spinning
up a _nix environment--surely no automated system could understand or be
trusted with the intricacies of setting ulimits to values obtained via a
function utilizing, at most, three inputs and grade school arithmetic.

Since I was more in their systems department I had limited opportunity to
observe their archaic superstitions about code structure, but the short
introduction course to M they provided confirmed that most current and new
employees were willing to accept that certain control flow tools or function
structures were dangerous because they were necessarily slower than something
that made sense in hand assembly programming, since there had obviously been
no developments in compiler optimization since M was designed (in the good old
days, before C existed).

~~~
logfromblammo
There were no archaic superstitions about code structure. Those had to be
removed, because the code had long ago grown large enough to push up against
size limitations. You couldn't put comments in the code. You _had_ to use the
abbreviated syntax. If you tried to make anything human-readable, it wouldn't
fit.

You weren't even allowed to touch the infrastructural M code. Mostly, you
worked on superficial or peripheral M code, or on the GUI in VB6. I heard
rumors of a GUI modernization team, but never saw any direct evidence of it.

It was a result of the iron grip of the top management. They didn't want to
yield control of the company to the people actually running it. You were
expected to use your expertise to do what you were told to do, in the best way
you could, while still remaining completely within your lane.

After the 6 months of training, I gave it a year to read the character of the
company, and then another 6 months to soak some potentially major family
health care costs with that sweet insurance plan, then spent 4 months job
hunting. It was the best employer-offered health insurance plan I ever had.

But make no mistake. Companies like Epic are why health care costs in the US
are huge and growing. Epic never refactors _anything_ that still works well
enough to hold together with some expensive human labor. It is a technology
company that runs on well-trained people instead of well-designed code and
processes.

~~~
__float
When did you work there?? I find it surprising you never saw anyone writing C#
or TypeScript if it was any time recent. These days there's quite a bit of
web-based UI replacing the VB6, though you might not notice if you don't look
carefully enough.

~~~
DanielFallon
If it was any more than a year ago, there were parts of the company that had
barely started and web migration due to dependencies. Epic is still slow
playing this to make sure they don't have some of the issues they had with the
early 2015 releases

------
NetStrikeForce
Many moons ago, during one summer before starting uni I had the chance to work
on porting a mumps application to... Visual Basic :)

That's the summer I decided I didn't want to be a programmer.

------
gameshot911
There are some cool features in M. One of the neatest is the ability to create
arrays on the fly.

Ex:

    
    
      >set array("node1")="Hello"
      >set array("node1","subNode1")="Hola"
      >set array("node1","subNodeX")="Howdy"
      >set array("node2")=39481
      >set array(19849,1,1,1,3,"Godzilla",5,8)="Greetings"
    

All dynamically created on the fly - no need to define the array in any way
ahead of time! The nodes are also automatically sorted after any
addition/deletion.

Looping over the arrays is very easy too. M has a function that lets you set a
variable to the next node.

Ex. (using the above example):

    
    
      >set foo=$O(array(foo)) - result: foo="node1"
      >set foo=$O(array(foo)) - result: foo="node2"
      >kill foo
      >set foo=$O(array(foo)) - result: foo="node1"
      >set bar=$O(array(foo,bar) - result: bar="subNode1"
      >set output=array(foo,bar) - result: output="Hello"
      >set bar=$O(array(food,bar) - result: bar="subNodeX"
    

Variables can also be created on the fly, and don't need to be defined as a
type ahead of time. (Technically you don't define them ahead of time at all,
if you want a new variable just set it to something!) They can be strings or
numbers, and you can change their type at any time by setting them to a new
value.

Pretty cool, and particularly easy for someone with no coding experience to
pick up. I'd only ever use it for managing a database, though.

~~~
gameshot911
Oops, in the 2nd example, output will equal "Hola", not "Hello"
(arr("node1","subNode1")). Also I'm pretty sure numbers are sorted before
strings, so in reality on the 1st pass foo would equal 19849.

------
comice
If you're registered with a local NHS GP in the UK, it's very likely that your
medical records are stored in a Mumps system.

~~~
jwdunne
Is that why the software they run looks like Win 95 era GUIs and, if you
listen really closely, makes the GP swear under their breaths?

~~~
strongai
I don't think so - I think that particular accolade goes to
[https://www.emishealth.com](https://www.emishealth.com)

------
play2computers
ESA is also using mumps...: [http://www.intersystems.com/library/library-
item/european-sp...](http://www.intersystems.com/library/library-
item/european-space-agency-chooses-intersystems-cach-database-for-gaia-
mission-to-map-milky-way/)

------
gumby
Unix MUMPS was written by Harlan Stenn, the same guy (somewhat famous for)
maintaining NTP on a shoestring.

------
janwillemb
I have worked in a place where we had to use Intersystems Caché Objectscript,
which is a variant of Mumps. It was terrible. For example, it was nearly
impossible to use source code control. We also tried introducing a unit test
framework to add some stability, but it turned out the .NET gateway we tried
to use to this purpose, wasn't thread-safe, had side effects, kept state in
mysterious ways. Restarting the cache' (sic) process was often the only
solution after the server totally collapsed while the automatic integration
tests were running. If course this was all our own fault for not understanding
the product properly, as Intersystems would often reply. At the time, it was
not funny. I'm glad I left.

------
Animats
It's NoSQL, the early years. Trees with fast lookup capabilities. Useful for
medical, which is basically tree-oriented. There's not much need for cross-
patient access in medical records. A wide variety of data structured in
different ways must be stored.

~~~
__float
Umm, there are still plenty of "cross record" lookups--patients have standard
types of encounters at the medical center, they take standard types of drugs,
and have standardized billing/symptom codes. These are all references to other
"tables".

------
amirouche
Some MUMPS based software use the EAV model cf.
[https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80...](https://en.wikipedia.org/wiki/Entity%E2%80%93attribute%E2%80%93value_model)

------
peter_retief
I used it about 7 years ago, it's a nice environment, fast and pragmatic. Not
so sure of the proprietary offerings called Cache I think?

------
megous
First thing I'd do if I had to program in this would be to create some
"something sane to MUMPS compiler". :D

~~~
dahakon
It has been done. FIS writes in a higher level language called Profile, which
is compiled into M code that can be run by GT.M.
[https://en.wikipedia.org/wiki/Profile_Scripting_Language](https://en.wikipedia.org/wiki/Profile_Scripting_Language)

------
buovjaga
Finland will soon be blessed with a magnificient MUMPS system:
[https://www.epic.com/epic/post/2118](https://www.epic.com/epic/post/2118)

------
zeruch
I took a MUMPS course at University (my professor at the time at UC Davis was
one of the language maintainers IIRC; a fellow named Dick Walters.

It was baffling in spots, but the M database was kind of neat. Overall,
someone else in this thread said it best "You can easily do lots of terrible
things in Mumps, but those things are usually more straightforward than the
terrible things you do in other languages. You can also do elegant things,
though a little less straightforwardly."

------
killjoywashere
As an end user of a Mumps codebase, I like the speed (our interface is a
VT-500 emulator over SSH to an OpenVMS machine), but the fact that there is no
table-row-column database means pulling research extracts requires logging
screen output to flat files, which then have to be parsed.

------
mabynogy
An SQL interpreter written in MUMPS:

[https://github.com/robtweed/node-
mdb/blob/master/gtm/MDB.m#L...](https://github.com/robtweed/node-
mdb/blob/master/gtm/MDB.m#L2456)

~~~
robtweed
Correction: this is actually an emulation of Amazon Web Services' SimpleDB
database. It includes an implementation of the SimpleDB SQL-like query
language - it's not a full-blown SQL interpreter.

------
defined
I worked in InterSystems M/VX (MUMPS for VAX/VMS) on a 2 year project in
1985/86\. We developed a wireless ambulance dispatch system entirely in M/VX
except for PDP-11 front-end processors that did the actual communications with
the UMCTs (Universal Mobile Control Terminals) in the ambulances.

It ran on a VAX 11/751 that was maxed out with 8 MB (yes, that's megabytes) of
RAM and a state of the art Fujitsu Eagle 400 MB (yes, that's megabytes) 14"
hard drive. The user interface was text-based forms on VT-100 terminals.

M/VX was selected because there was nothing available at the time that could
look up data nearly as fast as the M/VX B-Tree database, and we had to look up
a lot of map coordinates.

I wouldn't grace the data storage with a description of NoSQL - it was plain
and simply a multi-rooted hierarchical database, or less fancily, a set of
multidimensional disk-based associative arrays. As others have pointed out, it
differed syntactically from a memory-based array only by being prefixed with a
caret/circumflex (^). It certainly was damn fast (for the day).

Initially, it was so cool to be able to store something just by writing

    
    
        set ^address("US","FL","Miami","Main St",12345)=1
    

But the pain soon set in.

There were no such things as indexes. We had to create (and maintain) inverted
arrays for that purpose.

If we got the hierarchy wrong, it was murder to reorganize it. Queries were
only really possible if they fit into an existing hierarchy.

There was really no such thing as an ad-hoc query.

Hmm, maybe it _was_ kind of like NoSQL...

But the killer feature (as in, it killed us over and over) was falling foul of
the hideous global variable, $test, as others have pointed out.

I don't remember clearly, but if you wrote something like

    
    
        set a=1
        set b=0
        if a=1 open 1:"input.txt",old
        else  set b=10
    

the value of b after this would be 0 if "input.txt" could be opened, and 10 if
not. This is because open set $test to false if it fails, so the else
executes, even though a=1... the horror, the horror....

Oh, oh, oh... and the result of 2+3 _5 would be 25, not 17, because there was
no operator precedence. You_ had* to use parentheses.

So it was kind of amazing in some ways (because ambulance dispatch system in
8MB of RAM) but a horror show in so many others. I'm glad it was only 2 years,
and I did get to write some cool VAX PASCAL to allow M/VX to interface with
the FEPs.

~~~
jsgrahamus53
The VA took MUMPS and created a DBMS out of it, which would allow one to
define the schema and then use utilities to automatically update indices.

It is much nicer when the system remembers to do that for you.

There were gotchas in the language that required you to understand it and play
ball its way. Not unlike other languages I've seen. The payback was trememdous
flexibility and performance on minimal (for today) systems.

------
david-given
Cheesily copied-and-pasted from 99-bottles-of-beer.net
([http://www.99-bottles-of-beer.net/language-
mumps-415.html](http://www.99-bottles-of-beer.net/language-mumps-415.html)):

    
    
        Mumps is now called M or cache but it was originally called Mumps.
        See http://www.camta.net/aboutm.htm
    
        ; The following is a single line of code
        beer    ; Randy M. Hayman (haymanr@icefog.alaska.edu)
                for i=99:-1:1 w !,i," bottle",$S(i=1:"",1:"s"),
                " of beer on the wall, ",i," bottle",$S(i=1:"",1:"s"),
                " of beer.",!,"Take one down, pass it around, ",
                i-1," bottle",$S(i=2:"",1:"s")," of beer on the wall.",!
    

I've written compilers for GNU Make, and I've translated C into Perl, and that
_still_ makes my eyes bleed... so, as far as I can tell:

Commands can be abbreviated down to a single letter, so w = WRITE. Multiple
commands can be glued together with whitespace. Strings are as normal, but '
is the not operator. There is no => or <= operators; use `< or `>
respectively. There is Javascript-esque dodgy implicit type conversion from
strings to ints, but dodgier ("aa1"+1 is 1; "1aa"+1 is 2). Commands can be
suffixed with a colon and a boolean expression and they'll be executed
conditionally. $ precedes a function call. ! is the OR operator, except in a
WRITE command where it prints a newline. The @ expression is the equivalent of
eval(), and yes, all your local variables are in scope when it runs. $test
contains the value of the conditional in the IF command most recently in scope
(as distinct from conditional execution). ELSE is a statement which executes
the rest of the line only if $test is 0. Putting IF and ELSE on the same line
doesn't work (imaginary cookie for anyone who can guess why). An extra space
is required between commands if the first command takes no arguments.
Variables are global unless declare local.

I believe $S(...) is the equivalent of switch; $S(i=1:"",1:"s") contains two
conditions; if i=1, then ""; otherwise if 1, "s" (1 is boolean true).

The break statement is called QUIT. The return statement is also called QUIT.
The BREAK statement actually drops out to the debugger. The quit statement is
actually called HALT. the sleep statement is called HANG.

If a global variable is preceded with a ^, it is persisted by name to the
database; some versions have transactions. Arrays are key/value sets with many
indices. The docs say that trees are common, using a syntax like
^mytree(path,to,tree,node,from,root). ...which is actually quite cool.

I am torn between admiration for people who can get useful work done in this,
and horror that such a thing really exists in a non-ironic sense.

All that's from: [https://www.cs.uni.edu/~okane/source/MUMPS-
MDH/MumpsTutorial...](https://www.cs.uni.edu/~okane/source/MUMPS-
MDH/MumpsTutorial.pdf)

~~~
ijoker
Another thing that's really weird about MUMPS is that variables are
dynamically scoped. So this bit of code prints 5:

    
    
      foo() ; declare function foo
        n x ; declare variable x
        s x=1 ; set x to 1
        d bar() ; call bar
        w x ; print x
        q ; return
      bar()
        s x=5 ; set x to 5. Since x is not declared in this function's scope, it will search the symbol table of the calling function and overwrite its x
        q
    

I've run into so many bugs caused by something like this.

~~~
david-given
That'll be because there's only a single namespace, and the NEW command simply
copies the values of the named global variables onto the stack and copies them
back again at the end of the function.

I'm actually kinda used to that; I grew up with BBC Basic, which behaves the
same way:

    
    
         10 i = 0
         20 PROCtest1
         30 END
         40 :
         50 DEF PROCtest1
         60 LOCAL i
         70 i = 1
         80 PROCtest2
         90 ENDPROC
        100 :
        110 DEF PROCtest2
        120 PRINT i
        130 ENDPROC
        
        > RUN
        1
    

...it occurs to me that BBC Basic, at least the later versions with block IFs,
is a better language than Mumps in almost every way (except the integrated
database stuff)!

------
padseeker
I know this is not the focus of the post, but my favorite part of the website
is the book he wrote. Fantasy right wing fantasy dribble in the form of "The
Constitution Convention of 2022"

------
will_pseudonym
Was there already a programming language called Polio?

------
jsgrahamus53
I started coding in MUMPS 35 years ago, and have continued doing so for most
of the years since.

For my first 8 years I used a version called MIIS, which was developed by
Meditech. MIIS allowed 2 KB symbol space per job and 2 KB code space.
Amazingly we supported libraries, hospitals and laboratories. The hardware we
used were DG Eclipse and MV minicomputers; however, it also ran on DEC PDP and
IBM Series/1 machines. I remember hearing that the MV systems could hold 2 MB
of RAM, but it was found that the 2nd MB didn't add much performance-wise.
These systems supported dozens of printers and terminals.

Since then I have mostly used Digital Standard MUMPS (DSM) and Intersystems
Cache and again this has been in support of medical information systems. These
systems allowed for much larger memory partitions for each job. I coded CRUD
applications, reports and interfaces (both with other computers and with
automated instruments). I also developed inhouse web applications, using
Cache's advanced object system and SQL interface.

MUMPS/Cache runs on everything from the Raspberry Pi to mainframes. I knew one
guy who developed a multi-user accounting package that ran off of a PC-AT.
I've never heard of another language that could operate in multi-user mode in
such constrained conditions, except for Forth. Maybe C under Coherent? The
ability to run on different architectures enabled lab info systems vendor,
Sunquest, to increase their revenues by selling to clients who would only
accept IBM hardware, where previously Sunquest had only sold DEC boxes. I
don't believe much in the code had to be changed to facilitate the transfer to
mainframes. Yet another lab systems vendor, Antrim, used Micronetics Standard
MUMPS (MSM) on RS/6000 boxes. I worked on interfaces to automated lab
instruments for Antrim.

While my first MUMPS implementation was from Meditech, I had a different
experience from the individual who reported using Magic:

. MIIS had both global and local variables . I don't remember if variables had
to be capital letters, but other versions did/do not have such a requirement .
System functions were not so obtuse . Modern variations, such as Cache and
maybe GT.M from FIS, allow communication with other languages

While the early versions of MUMPS did not support object-oriented code or
graphical displays, they did support VT-220 style terminals and the displays
were quite nice. This was in the early 80's. So while some companies produced
products with roll and scroll, others supported formatted screens.

While MUMPS code looks odd to someone unacquainted with it, with a bit of use,
it becomes obvious. This is nice because most of the code I've seen still uses
single-character commands and 2 or 3-character function names. I really view
this as a matter of experience: Haskell code looks like gibberish to me and I
only understand a portion of Klong (which is patterned after K).

I had brief forays into COBOL and Fortran earlier in my career. And I
determined I preferred MUMPS: It made lots of things easier and avoided some
common problems in those other languages (such as moving too many spaces into
a Fortran variable - which would both clear the variable and part of the
program's code at the same time).

I really enjoy learning new languages and using them. I have coded a project
using bash, awk, and Klong, which was a hoot for me. And they all have tricks
which MUMPS does not have. Of course they are all just youngsters compared to
this almost 50 year old language, too. And while it may not be the best
language out there -- whatever that means -- it has powered libraries, credit
unions, medical systems (including the Veteran's Administration which has one
of the world's largest medical system), banks and stock brokers
(TDAmeritrade). I hear even the European Space Agency is using it to map the
heavens.

Perhaps most importantly to me, it has provided a means to feed and house my
family and in my later years allowed me to be mobile, through working remotely
(never even meeting my employer face to face). I imagine that it will continue
to morph and serve the data processing needs of many as the years roll on.

Thanks for reading.

Steve

------
throwme_1980
unfortunate name, Mumps is a contagious viral infection

~~~
BenoitEssiambre
...that can make your balls explode (so to speak) and render you sterile.

~~~
antiquark
Much like the programming language.

------
mlmlmasd
Professors and other high-ranking academic nerds: get your students to design
your websites, cause you always fuck it up. Lol.

