Pascal at Apple
blog.fogus.me
blog.fogus.me
Apple's Pascal had been extended to the point where there were few true differences between it and C, other than
- strings with busted semantics (size being part of the type being a huge mistake, leading to a proliferation of types like Str255, Str32, Str31, Str64, etc). I should add that C's strings were semantically busted, too, and in more dangerous ways. No way to win :-)
- nested procedures (not terribly useful in practice, IMHO)
- an object syntax, used for Object Pascal and MacApp (a complete, though large and somewhat slow app framework).
- some miscellany, like enums and modules
Apple extended Pascal pretty extensively, adding pointer arithmetic, address-of, variant functions calls, and a bunch of things I've forgotten. I could write some Pascal, then write some C, and squint and they'd look pretty much the same. Most people shrugged and wrote new code C if they were able, and then moved to C++ when CFront became usable.
1. Properly encapsulating their scope, as opposed to having static functions sit awkwardly somewhere else.
2. Factoring out common code within the function.
3. A lot of my need for goto statements vanished with nested functions.
4. Take the address of a nested function, and it serves as a lambda.
5. No need to create "Context" structs to pass local data to them.
6. They replace a lot of what C macros did.
7. They're inlineable, so are not costly.
I use them more and more as time goes by. It's a pity C doesn't have them, they'd fit nicely into the language.
int f()
{
struct local {
static int nested_func()
{
return 123;
}
};
return local::nested_func();
} int g()
{
int x, y;
struct local {
int & a_;
int & b_;
local(int & a, int & b) : a_(a), b_(b) {}
int operator()()
{
return a_ + b_;
}
} nested(x, y);
x = 99; y = 1;
return nested();
}
assert(g() == 100);I think I misliked Pascal's nested procedures because they weren't true lambdas; once the outer procedure returned, the inner procs were no longer callable (just one contiguous stack, right?). Early-on, using C++ lambdas, I found myself making the same mistake in a design for some asynchronous completion stuff. Embarrassing; C++ and Pascal are not JavaScript/Lisp/Scheme/Smalltalk :-)
It's funny in this way how c++ lambdas lead to very c++ specific issues and uniquely c++-ish solutions. I think the wackiness of the closure capture mechanism is the best example of this I can think of.
Or just have first class functions, and prototype based inheritance. Way more flexible and powerful than class based inheritance. See JavaScript 5 as an example, ask Crockford.
Static nested (i.e. local) functions in D can be static. What that does is prevent the function for accessing locals in the enclosing scope(s).
How does that work? Not immediately obvious to me.
T common() { ...common sequence of code... }
...
return common();
instead of: goto Lcommon;
...
Lcommon:
... common sequence of code ...
return result;I've done that for years with C and C++. Nested functions are so much nicer and clearer.
I found out that GetString converts a Pascal string to C without a length argument!
https://stackoverflow.com/questions/4083356/array-begin-from...
http://docwiki.embarcadero.com/RADStudio/Berlin/en/String_Ty...
Besides, there were arrays as well, and TPW had safer strings without that limitation PCharStr.
http://docwiki.embarcadero.com/Libraries/Berlin/en/System.Lo...
http://docwiki.embarcadero.com/RADStudio/Berlin/en/Migrating...
It always felt quite natural to me.
I think trading some programmer inconvenience for a world with no buffer overruns would have been a good thing, in retrospect!
https://en.wikipedia.org/wiki/Cfront
Interesting.
https://youtu.be/6tUWoy1tJkE?t=45m
The Pascal bits are from 45:00 to about 50:00.
...
My manager at the time said, no, we don't want to do this [Pascal],
people are happy with what they got. I overrode him and went to
Jobs, and Jobs said "Well, I'm not convinced. I think our users are
happy with BASIC and assembly language. But you seem passionate
about it. I'll give you one week to prove me otherwise."
I was on an airplane within two hours down to UC San Diego and I
started porting right away.
...
The other thing that happened then is I had to plug in the disk
routines, and their system was pretty big and that little 13-sector
floppy disk didn't have a lot of capacity. Well, Woz had just come up
with a different way of encoding the data on the disk so that we could
get more data for the same disk size, and we needed the 16-sector disk
routines. And so Woz came down, and I was there... I had never bothered
to get a motel because I slept on the bench when I wasn't working. This
is in the computer science lab at UC San Diego. I was busy, I didn't
have time to go sleep.
But Woz came down, and I got to interact with him and it was really fun
because he was working on installing these 16-sector disk driver
routines, and he'd go 'type type type type type' -- and he didn't type
in assembly language and have it assembled. No, he'd type in 6502
machine code. Hex. -- He'd type in hex, and then, you know, watching
him type and he'd go 'type type type' -- pause -- 'type type type type',
and when he finished I asked him what was the pause? And he said
"forward branch, seven instructions, I had to compute the offset before
I continued". So, he didn't back-patch the offset, he actually looked
at what he was going to be typing, knew how many bytes it would take...
he was brilliant. Next he created for the Apple II a version of Pascal, a high-level programming language. Jobs
had resisted, thinking that BASIC was all the Apple II needed, but he told Atkinson, "Since
you're so passionate about it, I'll give you six days to prove me wrong." He did, and Jobs
respected him ever after.
https://books.google.com.au/books?id=cf_2PBPP-rEC&pg=PT143&l...When will someone build HN for Audio/Video.
IIRC, the line my high school computer science teacher used about USCD Pascal without paying at the time (around 1988) was that it was out of copyright or something, but now that I think of it, I'm not so sure that was a legit reason.
I eventually moved to C (also using THINK C - see retrospective link below for a sample of those heady times) and never looked back until a couple of weeks ago I set up Lazarus for my kid to play with (there are too many Python GUI development options, and none halfway as good).
Lazarus is _amazing_ (if somewhat odd in today's world), and I really wish we had more IDEs like it instead of all the crappy Electron/web approaches for building desktop apps. It builds fast, tiny, entirely native apps in less than a second, and is an excellent example of how far Pascal went despite falling off the mainstream wagon.
(If anyone knows of anything like it for cross-platform desktop apps, let me know, I'd love to try it out)
- Link about early C dev on the Mac, that also mentions MPW and Pascal in passing - https://retrocomputing.stackexchange.com/questions/3213/what...
So we had to wait 20 years, failure of Moore's law, cache optimization issues, competition from new languages, for them to come up with .NET Native, CoreRT and the initial AOT on Java 9
In comparison, .net native and Core RT are tiny dots on the radar.
Besides,
- Pascal UCSD Pascal was a VM (p-code)
- A few anti-piracy schemes on the Apple ][ used their own VM to obfuscate their code
- ScummVM was extremely popular to create games
VM's were a thing in the 90s and they are even more of a thing today.
LLVM isn't a VM.
.NET achieved its position, because on Windows many of the APIs became .NET only or C++ COM. Not many people bothered to use alternatives to Microsoft tooling.
JVM achieved its position due to being free, and the huge amount of money and engineering resources that Sun poured into it, which in a way ended up killing the company.
Yet due to the pressure from Fintech customers, Oracle started to look into AOT compilation, with initial support for Linux x64 available on Java 9, other platforms will be supported later. Most commercial JDKs had support for AOT since the early days.
> In comparison, .net native and Core RT are tiny dots on the radar.
Yes, but that is where Microsoft wants to go. There is no pure .NET on UWP, other than via the desktop bridge, the transition technology to port Win32 into UWP.
> - Pascal UCSD Pascal was a VM (p-code)
Quite correct and it ran quite slowly, purely interpreted.
> A few anti-piracy schemes on the Apple ][ used their own VM to obfuscate their code
- ScummVM was extremely popular to create games
The games from Lucasart were hardly something where performance mattered.
> VM's were a thing in the 90s and they are even more of a thing today.
Given Apple's decisions on their programming languages, Go, D, Rust, Pony, Haskell, OCaml, the change of direction on Dart's design, I am not quite sure.
Your point, which I was replying to, was that VM's are a mistake, not that they were/are slow, or how some VM's became dominant, or making guesses toward where Microsoft or Oracle want to head.
My response is that 1) VM's are dominant today and 2) for very good reasons.
And because of that, they are not a mistake.
I also speculate they are going to remain dominant for a while because of all their advantages over native approaches, advantages which become even more prominent as hardware keeps pacing up, like it has always done.
That was more of a self-fulfilling prophecy than a need. There simply was a shortage of reusable compiler backends in the 90s, so when major companies (Sun, IBM, and Microsoft in particular) decided to devote all their resources to the JVM and the CLR, then those became easy targets for language implementors (and low-hanging fruit, too).
Regardless of what you think of them, their success is probably mostly the result of going where the most resources were being spent.
And besides, you mentioned than you'd prefer to stick with more functional languages. It's hard to prove someone's preference wrong. :)
I mostly share your preference, but I make an exception for Pascal. There's just something about it that draws me in, even though I've only used it for fun, and not professionally.
[1] "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." - Antoine de Saint-Exupery
https://www.brainyquote.com/quotes/quotes/a/antoinedes103610...
The thing that drew me in to Object Pascal was getting Delphi back in 1996 (I think it cost $200), and being just amazed at how much I could do out-of-the-box without knowing a thing about Object Pascal. The productivity with IDEs like Delphi/Lazarus is just astounding.
I look at setup instructions for many languages today and just cannot believe what I'm reading. Pages and pages of instructions on putting together a dev environment just to compile a Hello World program. It's just insane to me...
I've used Lazarus when I've had small GUI apps I wanted to make. Other times, I'll just use Turbo Pascal in DOSBox when I'm just trying to have some fun and make simple little games.
Check out Xojo. HN user SyneRyder sometimes comments about it here, and likens it somewhat to Delphi. Cross-platform too. I'm in early stages of trying it out, so won't comment myself on it.
Xojo is a BASIC variant, and IIRC, was called RealBASIC earlier. While I've done some work with BASIC and Visual BASIC in my time, and don't puke out on it (as some people allege they do :), I confess that I prefer the syntax style of the Algol family of languages, such as C, C++, Pascal, D, and Go.
However, the convenience of VB, Delphi, Lazarus and similar drag-and-drop GUI app builder tools is real. Great for quickly prototyping something, and many a time for the final product too.
But yeah, it delivers.
D meets some of your criteria too, at least somewhat small fast, native apps. Build speed is decent (or more) too, and it is designed for that - doesn't have C's repeated overhead of pulling in include files. [1] Haven't tried the GUI toolkits for D though (yet). There are some, like DLangUI, GtkD, etc. Not sure if there are any GUI builders like Delphi, Lazarus, VB, Xojo, etc. have. Also, I think I read that D's language design allows D compilers to be the single-pass kind.
[1] I think this is the video I had blogged about a while ago, in which Bjarne Stroustrup talks about the details of that include files issue:
Video: C++, Rust, D and Go: Panel at LangNext '14
https://jugad2.blogspot.com/2016/08/video-c-rust-d-and-go-pa...
Edited for wording about D compilers.
Sorry, typo - I meant to say "C++'s repeated ..."
C may have it too, don't remember if so or not right now.
The video mentioned in my above comment has some details on why this is such an issue in C++ - from the source, i.e. Stroustrup, the creator of C++. There's a bit of humor around that fragment of the talk - it is somewhere near the end, IIRC.
But there are good reasons it was surpassed by C. In early Pascal, you got a pointer by allocating memory; you could not get a pointer to an existing variable. You'd be surprised how often that gets in the way when implementing a data structure. Just try to implement the following function in C without using the address-of operator:
struct list *head = (void *) 0;
void push_back (struct list *entry) {
struct list **p = &head;
while (*p != 0) p = &p->next;
*p = entry;
}
Pascal got better. But once you've switched to C, the sheer verbosity of Pascal is bothersome. Instead of "{" and "}" Pascal uses "begin" and "end". It uses "procedure" or "function" to introduce a function.There's no going back, but I wish it was still available for learners. Java is comparable in terms of programmer safety, but has too much ridiculous boilerplate just to write "hello, world".
But the IDE makes GUI programming ridiculously easy, something Python can't compare on.
In terms of safety/dangerous code, modern Object Pascal style lets you be as dangerous as C if you want, but the default semantics are much more comfortable, and take you away from the danger zone more often.
Both Python and Pascal are relatively easy to get up and running with, and have pretty solid, standardized toolchains for industry use: in contrast C and C++ leave the build process relatively undefined and varying between compilers and platforms, which has resulted in a huge amount of friction to get any project building on a new machine.
Note that there are multiple Pascals, especially in the late 70s and 80s. Pure, true Pascal was annoying and restrictive [1].
No commercially successful Pascal was pure. The classic was Turbo Pascal which was disdained by purists but enormously successful. It's inventor went on to work on Delphi (a sort of Pascal which is still popular) C#, and Typescript.
https://en.wikipedia.org/wiki/Anders_Hejlsberg
1. e.g. semicolons were separators, not terminators. You'd get a syntax error if you had a semicolon after your last statement of a program/procedure.
The main drawback is that Pascal is not commercially successful, so you'll learn it and move on. Python, on the other side, is widely used, so Python knowledge is useful on its own.
Start from Pascal if you want to learn a lot of languages. I specifically would suggest to dive deep after Pascal and learn some assembly language, may be x86. They you'll have good basics and you can learn almost any language you want, C would be good, for example.
Main problem with Python IMO is that it's too high-level, it's dynamic, it uses GC. All those things are too far away from real machine code, so if you'll learn Python first, it might be hard to learn low-level programming and it's useful even if you're using JavaScript.
Start with Python and you're most likely to be stuck with dynamic typing/runtime mindset and it'll distance you too far away from OS level native land.
OTOH starting with Pascal, you'll learn a great deal of low level (well, relatively) stuff and that will make you appreciate the higher level languages when the time comes and will let you leverage them more efficiently. Also as a bonus, a big bonus I think, Pascal will let you feel at home if you ever need C/C++/D in your career.
The AP Computer Science exam used to be given in Pascal, BTW.
So although it doesn't quite make BGI graphics based apps run directly on Windows...it's still quick and easy enough to have some fun. I did it specifically to give myself a way to make programming fun again at a time when I was feeling a bit burned out from working on massive, overly complex C# and JavaScript code all day at the office.
Update: Here is the link to the Museum:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p026...
Pascal had `var` arguments, i.e. call-by-reference, which can be used for similar purposes. Call-by-reference isn't a complete replacement for C pointers, of course, but it also avoided the whole host of memory safety issues arising from C's more general model and which plague C to this day.
> But once you've switched to C, the sheer verbosity of Pascal is bothersome. Instead of "{" and "}" Pascal uses "begin" and "end". It uses "procedure" or "function" to introduce a function.
That's entirely subjective, I think. As somebody who grew up with Pascal and learned C later, I found the C syntax to be comparatively hard to read. I do favor the Modula-2/Eiffel/Ada approach of having "end" terminators instead of "begin" / "end" blocks (which share the troubles that braces have), though.
I understand avoiding excessive amounts of large boiler plate where standard patterns are constantly repeated for no particular reason, but that's not a comparable situation to individual keywords.
I love both C and Pascal, and I'm a guy who has done a lot of both of them. Hey, its possible to like more than one language. With that background, I think your above points are minor (IMO of course) and should not be an issue in deciding between the two. One can easily get used to "begin" and "end" instead of braces, or vice versa. Same for the keywords "procedure" and "function". Plus, editor shortcuts in modern editors should be able to handle that, or a keyboard enhancement tool like AutoHotkey, vim's abbr command, or equivalents in other tools.
Better still, use both languages, at different times, as per needs, wants, convenience, etc.
When I went to college in 1986, Pascal was the primary language used in all entry-level courses at Virginia Tech. (Turbo Pascal on an IBM PC -- $5 at the student stores, if you brought your own floppy. I'm the weirdo who brought a Mac Plus to school and used Lightspeed/Think Pascal.)
All of the classic Mac APIs used pascal calling conventions. Pascal continued to be the language used for serious Mac development for a long time.
I can't find any references via Google, but Apple had an internal language called "Classcal" which I was told was "pascal with classes". Eventually Think Pascal adopted this object-oriented Pascal syntax.
Just today I was thinking about how great it was coding in Lightspeed Pascal, when I was trying to get VS Code to display ligatures. Lightspeed Pascal parsed the AST and auto-formatted all your code for you. Tabs became tab stops, like a word processor. I still miss that; hard to believe today we're still fighting about tabs v. spaces.
Pascal was designed to allow single pass compilation of programs, while the C preprocessor alone was a source of what was immense overhead at that time. On CP/M, Turbo Pascal blew all C compilers out of the water in terms of compilation speed. The one C compiler I had on a ZX Spectrum at the time did not actually implement the full language so that you'd have some memory left over (I remember that the C type cast syntax was replaced with a keyword in order to simplify the parser, for example).
That said, UCSD-Pascal on an Apple II (which we got to use in school as part of our regular computer science course), was not all that convincing as an implementation (even if the system as a whole was fairly impressive). Because it used a bytecode interpreter (even if that bytecode interpreter leveraged type information and was much faster than a bytecode interpreter for a dynamically typed language), execution speed – including that of the development environment, which was written in UCSD-Pascal itself – was still pretty sluggish in comparison to an actually compiled language. (The UCSD p-code in principle also allowed compilation to native code, but at least the system I had access to – that was in the early 80s – didn't support that.) But it was still more pleasant than many other compilers, and that was at a time when cassette recorders were often still the primary external storage medium, so people were more tolerant, when their point of comparison was systems that literally included source code from cassette tape at compile time, because for large programs you couldn't fit both the source code and the object code into memory at the same time.
Also, from my recollection, Turbo Pascal was not just faster than C compilers. It was also faster than other Pascal compilers. And pretty much any other computer regardless of language. That was part of its appeal.
[Edit: to be clear, neither of these were the UCSD Pascal referenced in the original article; I had that on my Apple II in college, and demoed a baseball statistics program I wrote in it to the THINK people as part of my job interview.]
They also had a pascal. Granted it was targeted to the IIGS rather than the straight II line, but given my personal experiences running apple pascal on a machine with only a single floppy drive it was just as well. In a way Jobs was right, BASIC+assembly were a better target for the 8 bit apple II than pcode and the long development turnaround time for pascal. Worse the resulting applications were slow, not just running but the extra delay loading the pascal system from 5.25" disk rarely made for a good user experience.
That said, to this day, I compare all new languages I learn to object pascal/delphi, and frankly I have yet to find one that seems as polished, productive, well documented, resistant to bugs, etc.
When did Virginia Tech switch from Pascal to C++? I did my undergrad there in CS between 2002 and 2006 and the introduction courses were in C++ by then (though I believe they now have switched to Java and Python).
The only exposure I had to Pascal was implementing a compiler for an undergraduate and graduate level course for a subset of the language's features.
Meanwhile, the Apple ][+ could only display 40 columns on screen, where of course by "screen" I mean "television". (You could buy another big card to give you enough memory to display 80 columns at a time, but who had the cash to make another huge purchase like that?). Of course, 40 columns isn't enough to write in a structured programming language with indentation like Pascal, and in fact the Pascal program itself supported logical lines of up to 80 characters.
This issue was resolved as brilliantly as you might expect. You could toggle between looking at the left half of your program (cut off at the 40-character mark) or the right half. I'm not kidding.
A full-sized Apple card was a good bit less tall than a PC AT card and had to be angled to fit the case. e.g. [0]
I'm currently attempting to write a C compiler and the complexity is incredible compared to Oberon or Pascal. Sometimes I regret choosing C over Pascal as I'd probably be done now with the compiler, as it is I've only got the parser and preprocessor implemented.
Eiffel is another language that didn't gain a lot of popularity but is very interesting to read about. Bertrand Meyer, the creator of Eiffel is now at ETH Zurich, where Wirth spent most of his career. It's a very nice language that didn't achieve a lot of popularity, but some of the ideas, such as preconditions and postconditions, have been used in other systems.
The downside of this philosophy was that aspects of interacting with a computer that were inherently messy tended to be swept under the rug: The original "file" and "string" concepts as described in early Pascal reports were simply unworkable, and combined with a marked disinterest in language standardization efforts (which I personally suspect stems from Wirth's involvement in Algol 68, although I have no direct evidence) led to each implementation rigging up their own ad hoc solutions.
As a consequence, even TeX, a batch program with no fancy demands on hardware, was not written in strictly "standardized" Pascal, but basically Knuth had to assume the existence of a number of non-standard mechanisms.
Other than that, TeX actually used a strict subset of standard Pascal; quoting module #3 in Volume B of Knuth's Computers & Typesetting: "Indeed, a conscious effort has been made here to avoid using several idiosyncratic features of standard PASCAL itself, so that most of the code can be translated mechanically into other high-level languages. For example, the `with' and `new' features are not used, nor are pointer types, set types, or enumerated scalar types; there are no `var' parameters, except in the case of files; there are no tag fields on variant records; there are no assignments real:=integer; no procedures are declared local to other procedures."
As you also say, Pascal had virtually useless string types, but TeX worked around that limitation itself, by managing its own string pool in a single big array of characters, with a second array of pointers to where each string started. A string was identified by its index in the later array. Through careful design and coding, no general garbage collection of strings was necessary, just the ability to forget the most recently-made string.
[1] https://archive.org/details/Apple_Pascal_History_DTC_1992
The best thing I've loved were the .TPU files (but not sure whether TP4 or TP5 had them truly). There were no .h files to be included, or .lib (.a) to be added, it worked just magically well (with some limitations).
I've moved to C/C++ later simply because, well it's a stupid reason. I was writing a "File Manager" like app for DOS (just single column, not like Norton Commander, FAR or Midnight Commander), and the only function in Turbo Pascal 5.0 to move files was just renaming a file in the same folder... Had I known about inline assembly and be more brave, I would've stayed in Pascal Land (And I was already familiar with Ralph Brown's Interrupt List)... But hey, this stupid reason moved me to C/C++ as the builtin function there did it... then again, soon after that I've started using more and more inline assembly.
I love C/C++ now (especially C), and where I used to be really good at Pascal, I might have some hurdles reading pascal code today. Delphi was my last stop, and while I like it, I switched to video game development, and Pascal was not much used there (... Age Of Wonders I believe was written in some form of Pascal and possibly some other games,... Also part of Xoreax's IncrediBuild might've been, especially the part that does the C/C++ header processing, I think it was since we had issues with it, and while debugging found something pascal-ish in there, but don't remember now).
Anyway, Pascal was very common in education back then and Apply was very common in education...ergo, Apple and Pascal went together a lot of the time.
http://blog.fogus.me/2017/07/20/pascal-at-apple/#comment-808...
Pascal was great for people who didn't have curly braces in their muscle memory. But I suppose I've gone fully over to the dark side now.
In the last few days, I've gotten FreePascal compiling for it, bit I would also like to have languages that I can compile or interpret on the machine itself.
And yet, when I clicked on this part of me was really just hoping this was referring to nvidia's Pascal architecture, a hint that maybe they were finally dropping the Radeon line and getting some decent video cards into their machines.
One can but dream I guess.
It's 2017. Turn on your JavaScript.
https://blog.yell.com/2016/04/just-many-web-users-disable-co...
I like to avoid Javascript where possible just to build a nice clean fast page.
Why do people hate the idea of documents so much? Imagine if you had to suffer through a different app for every single book you read; that is what a js-mandatory page is.
And I still think disabling JS is like shooting yourself in the foot on purpose.
Two wrongs don't make a right. Also I'm tired of people who always have to point out "hurrr durr site don't work without JS". Nobody cares.
Apparently enough nobodies to tire you out.
It doesn't bother me to turn on Javascript when a site needs it. (If I complained about every site posted to HN that needlessly required Javascript I'd never get anything done...)
I'll turn it on by default as soon as websites stop abusing my CPU, battery, and bandwidth with their gluttonous scripts. On my machine, with sites I visit, the browsing experience is perceptibly better (and the machine stays much cooler on my lap) w/ Javascript selectively enabled.