Hacker News new | past | comments | ask | show | jobs | submit login

> in the sense that the limitations and exclusions of the language design were precisely what made compact implementations possible and widely successful.

All of the Pascals that were widely successful extended the language in key ways. I was an initial fan of Pascal, until I discovered that a large amount of my time was spent trying to work around limitations of the language.

With C, those workarounds disappeared and I was far more productive.

(I know C compilers always have numerous extensions, most of them of dubious value, but still, plain C remains a far, far more useful language than the Pascal of "Pascal User Manual and Report". Which is why C buried Pascal.)




As I said in another forum earlier this week,

"A lot of the hate centered around how it wasn’t a systems programming language, when it wasn’t supposed to be one. It’s like complaining your driving instructor’s car can’t be used to dig a trench without extensive modification."

After BASIC, I learned on Pascal (Apple and IBM). It was invaluable to clarify in my mind how programming structures work, as opposed to the (fun) chaos of early BASICs. I really didn't need much more than the I/O available in standard Pascal at the time. And it hid details like endianness that I was not yet ready to handle.

Were there problems? Of course. Among others, the vendors should have done a lot more to standardize extensions, the P1 parameterized array bounds should have been in the initial spec, and while the P-machines had many virtues, performance was not one of them. Far too many of the early implementations just ran the P-code in an interpreter.


While there may be general agreement that Pascal is a great teaching language and a weak systems language, I believe that early versions of mac operating system (system N, not OSX) relied heavily on a modified version of Pascal. Perhaps Steve did not get the memo.


Becaues Clascal/Object Pascal had an enormous number of non-standard extensions to make it a much more system and apps oriented language than the 1973 version. I believe Bill Atkinson was involved in the decision. Same story with TurboPascal and Delphi.

Walter's complaint is partially that it needed extensions to do anything non-educational on 1973 hardware. This is true, but to me is vaguely non-sensical, as it clearly had not been designed for that and was labelled as such.


It's been well over 40 years since I wrote Wirth Pascal code, but one of the problems was one couldn't write a line without a line ending. That's not an activity confined to system programming!


Sure. But for the output of the tiny calculator class project we did, it just didn't matter.


Yes, Pascal is good for that purpose.


Many of the decisions for Pascal seem aimed for a teaching language as opposed to a production language. For instance, in a production language, optimisation of generated code is worth a longer compile cycle, but in a teaching language (where programs are repeatedly resubmitted until they barely run, and then are never touched again) short* compile cycles are everything and quality of generated code is an afterthought.

* and cheap: I remember in the days of 30 engineers sharing a VAX that if one person was compiling at a time everything was snappy, but (especially near the end of quarters!) if ten people tried compiling at once interactive latency suffered greatly. Classroom use must've been even worse.


Many of the decisions for Pascal seem aimed for a teaching language as opposed to a production language.

Because it was. The fact it could be extended in so many ways to be a production language shows it had 'good bones', but many practical issues, like I/O, were left as an 'excercise to for the student'.

There seems to have been a lot of revisionist history around Wirths passing with people using Pascals limitations as an indictment of his PLT creds, virtually all of which ignore he was an academic working in academic environment on topics that interested him at the virtual beginning of programming on very, very limited machines. It's like calling Watt a hack because he didn't also add a supercharger and emissions control to the steam engine.


Here's what Wirth wrote about it in retrospective, and yes it was explicitly designed as a teaching language with a syntax suitable for a recursive descent one pass compiler http://youtu.be/5RyU50qbvzQ


> For instance, in a production language, optimisation of generated code is worth a longer compile cycle, but in a teaching language (...) short* compile cycles are everything and quality of generated code is an afterthought.

I don't think this is a valid take. It sounds like an attempt to rationalize away awful build times from some systems language. C++ has atrocious build times, but in contrast C compiles almost instantly. Other production languages such as C# and Java also have fast build times.

I don't think long build times are correlated with optimization or production-ready code. They are however linked with attempts to get compilers to do a lot of work just to get our code to generate machine code, but some of that work is due to how some aspects of a programming language sucks and require more work just to pull off an optimization.


> but in contrast C compiles almost instantly

was that the case 30 years ago?


For some compilers, yes.

Also, code was a lot shorter in those days.


Haha, so true! The Caltech PDP-10 slowed to an agonizing crawl the week before finals. Even though playing games on it was banned for that week.


Original Pascal was a teaching language. That's all.


Are you saying that Pascal dialect had WriteLn but not Write?


No, it has write(), but some versions on some OSs needed an eol to flush the buffers. In general the file ops were deliberately underspecified [1], but it was 1973 and the variety of OSs was much weirder than today.

[1] https://www.standardpascaline.org/The_Programming_Language_P...


> It’s like complaining your driving instructor’s car can’t be used to dig a trench without extensive modification.

Correct. But then you get hired for a trench-digging job, and told that you have to use the car, because reasons. And so you wind up really hating the car, when the problem was the other people who decided that it was the right tool for that job.


> But then you get hired for a trench-digging job, and told that you have to use the car, because reasons.

That's not a problem caused by the car. That's a problem caused by someone looking at a worksheet, see "dig a trench" in it, and promptly say "this looks like a job for my trusty car.".


> It’s like complaining your driving instructor’s car can’t be used to dig a trench without extensive modification.

It's more the other way around: learning to drive on a trench digger. Then you find out that what you really need on the places people actually drive, like a freeway, is a car.


Agreed. Pascal made it simple to understand fast and I was in productive flow.

Then suddenly I realized there are stuff I cannot do with it. That was the last day I used Pascal - and I remember it like my dearest experience in programming!


Pascal also has had numerous extensions.

No one used Pascal of "Pascal User Manual and Report" from 1976.

Strangley compiler extentions are only cool when talking about C, in fact, most C developers have no idea what ISO C is actually all about.


I did, in 1986 through 88. The only extension it had was separate compilation. (This was on PDOS running on a 68000, for the morbidly curious.)

And I agree with WalterBright. Unextended C was far more usable than unextended Pascal.


From the looks of Small-C and RatC not really that usable.

During the 1980's there was already several usable Pascal alternatives, plus Modula-2 came out in 1978 exactly to fix the shortcomings of Pascal without extensions, and the largely ignored ISO Extended Pascal came in 1991, retifying many of the 1980's common extensions.

Using original Pascal, was really when there was no alternative, like myself trying to fit some form of Pascal compiler into a 48 KB on top of Timex 2068 ROM, which naturally wouldn't fit.

Neither did the Darthmound BASIC JIT compiler for that matter, or one of those Small-C / RatC alternatives.


I remember the Modula-2 crowd being rather bitter that the advent of C++ sunk M-2. One of the M-2 compiler guys ruefully said to me "I backed the wrong horse." (Zortech C++ had taken the PC market by storm then.) The success of ZTC++ is why Borland changed direction from Pascal to C++. I heard rumors that Microsoft had been internally developing its own OOP language, but abandoned it and switched to C++ also after the success of ZTC++.


Borland did keep supporting Pascal in addition to C++ then, no? They introduced Object Pascal with Turbo Pascal 5.5 IIRC, and later kept extending that with Delphi. As far as I know, their strategy was playing both Pascal and C++ up through the bitter end with Delphi and C++ Builder. I don't know which of them, C++ or Pascal/Delphi, but Delphi was certainly popular enough at its heyday.

Obviously, Object Pascal was a very far cry from the Pascal User Manual and Report, and even at its extended version it was strictly less powerful than C++, so your point still stands. But it was more beginner-friendly. In my opinion, the moment you got beyond the basics (no pun intended), it was friendlier than BASIC or Visual Basic, while far more powerful. That was quite a sweet spot.

Once I felt comfortable with C++, I couldn't go back to Pascal. Even with the extensions, there were some things that were too painful for me like lack of RAII, lack of Generics, short strings by default. Perhaps some of these are addressed by Free Pascal or modern versions of Delphi nowadays, but that ship has sailed. I feel like Pascal with its extensions worked great in the 1980s and 1990s, and I have very fond memories of my time using it, but it just doesn't have much to offer anymore. There are other beginner friendly languages out there that are powerful enough and have better tooling and far larger communities. And it was all about the tooling and community all along.


To this day, many of the C++ Builder libraries are actually written in Object Pascal Delphi's dialect from Borland.


Are you ever wondering what would have been if you had not written a C++ compiler?


However, Wirth himself realized the problems of Pascal and his later languages are basically improved versions of Pascal -- Modula, Modula-2, and Oberon. But these languages didn't even really displace Pascal itself let alone C -- but maybe if he had named them in a way that made it clear to outsiders that these were Pascal improvements they would have had more uptake.


Object Pascal got most of those improvements, hence why it was hard for them to be adopted, maybe if a big OS vendor had picked them instead of C++, or later Java it would have helped.

At least we have some of Oberon ideas living on Go, which despite my usual rants, is preferable to plain C.


One could argue that C's success is largely because it was even simpler than Pascal and more generic --- a notable example is that Pascal has I/O built-in to the language, while C defined them as part of the standard library (which could even not be present.)


From a compiler writer's perspective, C is much more complex than Wirth's Pascal.

Pascal's builtin I/O was a major impediment to its usability.

However, one really great feature of Wirth's Pascal is nested functions with access to outer scopes, which D wholeheartedly embraces. They really are slick. I use them heavily.


> one really great feature of Wirth's Pascal is nested functions with access to outer scopes, which D wholeheartedly embraces

Can you give an example? What does the function access in the outer scope? Is it like an environment-capturing closure?


It can access the variables in an outer scope:

    int moon(int s)
    {
        int sum(int x) { return s + x; }
        return sum(3);
    }
An extra parameter is passed to the nested function, called a "static link", which is a pointer to the stack frame of the statically enclosing function. This is in addition to the usual "dynamic link" which is a pointer to the stack frame that called the nested function.

Nested functions can also be nested, and can access variables in enclosing functions by walking the static links back.

The neato thing about this is it makes stack frames work exactly like members of a struct. In fact, a pointer to a nested function is analogous to (and binary interchangeable with) a pointer to a stack object.


My first (and only) serious compiler had such nested functions, though without stack frames. Instead my VM had two stacks: one for function arguments and locals, and the other for return addresses, same as Forth.

I had no stack frame at all. Instead, the compiler kept track of the stack offset of every accessible local (relative to the top of stack). That way the implementation of my nested function was kind of trivial: there were no difference between true locals like `x` and locals from an outer scope like `s`, except of course for the possibility of shadowing.

One reason this was not special is that internally, it was nested scopes all the way down: there was one scope per local variable, so merely declaring two variables already means dealing with nested scopes. Once that was out of the way adding nesting functions was really easy (I believe it added less than 20 lines to my compiler).

Nowadays I think I would use a single stack instead, but if my language is simple enough I’ll probably skip the frame pointer and just keep track of offsets like I did this first time.


if your outer function f called a function 'quicksort' which called a function 'partition' which called your nested function 'compare', how did 'compare' get access to the variables of f from its statically enclosing scope? how did it know how many locals 'quicksort' and 'partition' had pushed onto the operand stack?


Err… I think recursive inner functions would just blow up… oops.

I guess it’s a good thing I didn’t advertise inner functions and only used them in the standard library…


well, that's the problem the static link solves; it's not such a difficult thing to implement if you let procedure values (function pointers) be two words instead of one. gcc emits trampoline code onto the stack at runtime to support this without breaking abi compatibility, so the pointer to the nested function actually points to the trampoline, which just supplies the static link and calls the real nested function


Do you know if that’s how C++ lambda functions work?

    auto sum = [=](int x) { return s + x; }


Almost, the nested function goes out of scope too if the outer function finishes.


True. D handles that complication allocating such scopes on the GC heap, if the nested function survives the termination of the other function.


I get that the C syntax is very awkward, compared to Pascal's. Are there more reasons that make C compilers more complex than Pascal ones, and would you tell which, please? I'm curious.


> One could argue that C's success is largely because[...]

Why do so many ignore the obvious? Ergonomics matters. At a time when most programmers didn't touch type (even the big stars), the economy of being able to type `int foo(int bar) { ... }` is a major productivity boost in comparison to `PROCEDURE foo(VAR bar: INTEGER); BEGIN ... END foo;`. Hell, that even bothers modern programmers. I mean, I know people whose entire reason for switching to Chrome when it came out was that the toolbars at the top of the screen were 18 pixels shorter or whatever. That's it. People are incredibly capricious.

Factor in the environment—Unix has a widely acknowledged beauty/elegance in its design—and it's not hard to see why people gravitated to C, even at a time when Pascal was anointed as the official development language by Apple for a platform where people were known to be able to make money writing apps and selling them to businesses and consumers alike.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: