[HN Gopher] The seven programming ur-languages (2021) ___________________________________________________________________ The seven programming ur-languages (2021) Author : surprisetalk Score : 296 points Date : 2023-05-04 10:47 UTC (12 hours ago) (HTM) web link (madhadron.com) (TXT) w3m dump (madhadron.com) | [deleted] | vidarh wrote: | My big quibble with this is that the OO category is _way_ too | narrow. The way it is worded it excludes almost all languages we | 'd currently consider OO, and is so strict it largely makes the | category pointless. Loosen it to exclude the "You do | conditionals..." bit, and focus on the message passing, and e.g. | Ruby and other languages that are message passing focused to the | point of it tending to dominate semantics over it's Algol-related | _syntax_ fits firmly in this category. | | Listing Self rather than Smalltalk as the basis of OO languages | is also a bit odd. Calling it a "purer form" I guess is _a_ | justification, but the other view is once you losen the | definition as above, self is just the root of one small (albeit | influential, via Javascript, branch of OO languages that almost | all owe more to Smalltalk than Self. If another language than | Smalltalk should be at the root, it should be Simula, for | inspiring message passing, not Self. | notacoward wrote: | > Listing Self rather than Smalltalk as the basis of OO | languages is also a bit odd. | | That was my first reaction too. I also agree that Simula | deserves a mention here. AFAICT more languages derived from | that model than from Smalltalk or Self directly, and I'm pretty | sure the authors of later languages such as C++ have | acknowledged as much. | Mesopropithecus wrote: | The author's notion of OO is intentionally narrow. I don't | know about Simula, but C++ is still reasonably close to | Algol, compared to what Smalltalk and Self bring to the table | (the author also mentions programming environments vs. text | files). | | If you accept that narrow definition at least for the scope | of the article, it makes sense. | int_19h wrote: | Simula itself was almost a superset of Algol-60. It's | pretty much Algol-60 cleaned up a little bit and with a | Java-like object model bolted on top. C++ is a direct | descendant of that, sometimes even syntactically - e.g. the | keywords "class", "new", and "virtual" all come from Simula | where they had largely the same meaning. It's close enough | to our mainstream OO languages today that Simula code can | be easily understood, at least so long as it doesn't use | the async features: | | https://rosettacode.org/wiki/Abstract_type#Simula | vidarh wrote: | It's _exceptionally_ narrow, in that it rules out the vast | majority of languages that even purists would agree are OO. | | E.g. in Ruby you can not take the value of anything and get | anything but an object (e.g. integers are objects, true is | an object, nil is an object), but Ruby is not an OO | language by the article's definition because it fails the | part about conditionals. | | Even though you can do this in Ruby (probably buggy, just | threw it together) - it's just not idiomatic and the | language has syntactic sugar for "less OO" forms: | def true.ifTrue; yield; true; end def true.ifFalse; | true; end def false.ifFalse; yield; true; end | def false.ifTrue; false; end (1 < 5).ifTrue | { puts "TRUE!" }.ifFalse { puts "FALSE!" } # Or: | (1 > 5).ifTrue { puts "TRUE!" }.ifFalse { puts "FALSE!" } | | So it might make sense if you accept that narrow | definition, but I don't think many people will find that | narrow definition to make sense. I certainly don't. | vidarh wrote: | Yeah, most Stroustrup and Gosling has acknowledged that, at | least. | | The reason I'd be ok with Smalltalk there is that Smalltalk | at least was a significant break and you _could_ argue that | many of the "non-Smalltalk-y" OO languages are really ALGOL- | derived languages that took _some_ OO aspects ( _especially_ | if you move Ruby out of the ALGOL bucket) in that most of | them tend to combine support for both non-object types and | objects, and have lots of constructs that operate on non- | object values. | | As such I can see the merits in both/either of Smalltalk and | Simula treated as the "ur-language" for OO in a way I can't | for Self. | | Self is remarkable, but as I've mentioned before, more for | the advances its implementation brought. | OkayPhysicist wrote: | From the perspective of "Here is a list of language families | from which you probably should learn at least one of each", the | message-passing OO languages are completely divorced from the | class-based OO languages. Tossing the latter in with the ALGOL | languages is probably fine, as long as the actual language-to- | learn recommendation is one of them. | TheRealPomax wrote: | I'm a bit confused about this quibble when the article text is | about "Self and Smalltalk", not just Self? If anything the | quibble should be "why is the section called Self when it's | about the _two_ ur languages Self (the ur language for | prototype based OO) and Smalltalk (the ur language for class | based OO)"? | vidarh wrote: | The title is "Self (object oriented programming)" and it ends | with "Self disposed of the notion of class and worked solely | with objects. As this is a purer form, I have chosen Self as | the type specimen for this ur-language", so while it gives | Smalltalk the space it deserves, it then turns around at | points out Self as _the_ ur-language for OO. | TheRealPomax wrote: | You seem to confuse "ur language" for meaning "the original | that others came from", which makes sense if you're | familiar with the term "ur", but is not how this article | uses the term. They use it to mean type specimen (as noted | in the article). As type specimen, Self makes a lot more | sense: it took the OO concepts pioneered by Smalltalk and | then made them _even more OO_. | vidarh wrote: | As type specimen self makes _less_ sense to me. In that | sense it might make sense as the ur-language of it 's own | type (prototype-based OO languages), but it's too | specific to be a specimen of the overall OO category. | | I don't agree it made the concepts more OO in any sense. | Self's changes feel far less significant than what | Smalltalk brought to the table. That an object inherits | it's structure and functionality from something that is | itself an object is true of all Smalltalk derived | languages I'm aware of, after all. | TheRealPomax wrote: | Smalltalk says "objects are instances of some class of | thing", whereas Self went "no, objects are just objects, | and what class of thing they are is mutable". | | Since we can get from Self's model to Smalltalk's model | by adding restrictions on what you can do to both objects | and prototypes, Self is quite objectively a better type | specimen. I wouldn't call it an "ur language", that was a | silly choice in term, but as basis for discussing OOP | models, it's the most permissive, and you can get the | other OOP models by adding various (sets of) | restrictions. | | (Much like how a regular grammar is a context free | grammar with additional rules) | vidarh wrote: | I suspect we'll have to agree to disagree on this, as I | don't agree with you at all that it is "objectively a | better type specimen". I'd argue it's not even a _good_ | type specimen, in that it shares fewer characteristics | with the majority of OO languages than Smalltalk does. | | The _defining aspect_ of OO languages if we go by Kay is | message passing and late binding. How that is achieved is | secondary to the classification. Both Self and Smalltalk | provides that, but Smalltalks way of providing that is | more typical of the class of languages as a whole. | | To me, either Kay is authoritative, or we go _the other | direction_ and include more of the ALGOL-derived | languages. In neither case is Self a good representative | of what OO languages are like, and that to me makes it a | poor type specimen. | TheRealPomax wrote: | He was absolutely authoritative, but: back in the early | days of OOP. Both the meaning and fundamental aspects of | OOP have changed (quite a bit) since then, and what Kay | called OOP might be the historical forefather to, but not | current type specimen of, OOP. | | So yeah, we'll have to disagree. | codeflo wrote: | I always thought that the "message passing" style of OO (which | I always hated as a term, because it implies asynchronicity, | but I digress) is firmly something else than the "classes and | interfaces" style of OO, and that it's an unfortunate accident | of history that we give them the same name. | vidarh wrote: | I think part of the problem of trying to separate the two is | that the most prominent implementations appear deceptively | similar on the surface, even with unfamiliar syntax. E.g. put | even Smalltalk in front of someone familiar with C++, and | they'll quickly latch on to the similarities once a few of | the basics are explained, to the point that explaining | message passing as different from method invocation is | tricky, not least because so much of message dispatch is | implemented in terms of method invocation. | | This is ironically exacerbated when what is often presented | as the important bit of Smalltalk are examples like the one | in the article of allowing definition of control structures | (you can do that in Ruby too, e.g. a partial impl: "def | true.ifTrue = yield" - now you can do "(1 < 5).ifTrue { ... | called if true }" - with a bit more thought you can chain | ifTrue/ifFalse). | | But while that's neat, that doesn't even require dynamic | dispatch, just the combination of being able to invoke | methods/dispatch messages to true and false, combined with | convenient syntax and support for closures. You _could_ add | that to a language and still not have a Smalltalk descendant | in any meaningful way. | | What matters much more is that objects at least _may_ take | control over the target of a message dispatch even if they | often don 't, whereas method invocations in "those other" OO | languages is mainly controlled by the class definition, and | that is often glossed over as an advanced subject or "scary | magic". For example how Ruby ORMs tend to use introspection | to let you dynamically treat columns on database tables as | methods based on the actual current schema of the database - | in other words the ability to do not just dynamic dispatch | but late binding. | em-bee wrote: | this distinction is something i have been struggling with | for some time. i am coming from pike which only uses method | invocation terminology (in pike it's actually called | "function call"), and never even hints at message passing, | yet in pike objects can take control over the target of a | function call and even dynamically create functions based | on arguments given. | | when learning smalltalk i could not see the what was so | special about message passing, and why it is even called | that. | | consequently, i find the distinction between message | passing vs function or method calling academic. more | interesting are distinctions like static vs dynamic | dispatch and early vs late binding and whether things are | defined at compile time or runtime. | | the term "message passing" always made me feel like this | should be something completely different and not even | remotely similar to function calling. yet i couldn't see | that difference and that left me irritated because i felt | like i was missing something. | dfox wrote: | ST80 does not really do the object controlled message | dispatch that was there in earlier Smalltalks. Well, you | can override Behavior>>#doesNotUnderstand: and do all sorts | of cool tricks with that, but it is mostly meant as error- | recovery path (which is partly apparent from the name), not | as something that should be regularly used. | | One weird aspect of Smalltalk that more or less directly | comes from the control structures implemented as messages | taking blocks is that on the language level there are two | distinct function-like objects: methods and blocks (ie. | lambdas) that behave differently and interact with each | other (return statement is scoped to method and only valid | during the dynamic extent of said method invocation). | vidarh wrote: | > ST80 does not really do the object controlled message | dispatch that was there in earlier Smalltalks. Well, you | can override Behavior>>#doesNotUnderstand: and do all | sorts of cool tricks with that, but it is mostly meant as | error-recovery path (which is partly apparent from the | name), not as something that should be regularly used. | | The same way you can override "method_missing" in Ruby | but you apply it as rarely as possible, _but the dispatch | is still dynamic_ and methods can be overridden and | dynamically defined. That 's the point. Not that you | literally implement a dispatch directly on the object. | | Put another way, the main distinction is that the precise | method body invoked by sending a given message to an | object _may_ be impossible to statically determine. | | > One weird aspect of Smalltalk that more or less | directly comes from the control structures implemented as | messages taking blocks is that on the language level | there are two distinct function-like objects: methods and | blocks (ie. lambdas) that behave differently and interact | with each other (return statement is scoped to method and | only valid during the dynamic extent of said method | invocation). | | Ruby sort-of inherits this too, but at any point where | you take the value of a block, it becomes an object - | it's purely an implementation artefact, and with | lambda/proc providing both lexical and method-local scope | for return. | nostrademons wrote: | Agree on the families, but I would pick a different | representative for many of the categories. | | Algol -> C. Mostly because you can actually do things with C, and | yet it remains a fairly small language that's a relatively pure | exemplar of the Algol tradition. | | Lisp -> Scheme. Also because it's a tiny language that tries to | push the fundamentals of the Lisp family (code-as-data, | recursion, functional programming, macros) as far as possible. | | ML -> Haskell. ML is eager, Haskell is lazy. If you're going to | learn about the ML family, you might as well learn the concept of | lazyness, which results in a very different style of programming | than FP of the Scheme variety (in the Lisp family). | | APL -> J. The usage of special symbols is largely irrelevant to | the concepts in APL, and it's a barrier to accessibility. You can | learn all the important parts of array-oriented programming with | J and use actual words to do it. | | Self, Forth, and Prolog I would keep as exemplars of their type. | I would also add TCL as another ur-language for string-based | scripting languages (with Perl, PHP, and SNOBOL as other | representatives of the category). | pklausler wrote: | The more important distinction IMO between ML and Haskell is | that Haskell is truly pure. | abrudz wrote: | Yeah, K doesn't even have proper n-dimensional arrays. Funny | enough, the author writes "If you do a lot of numerical work, | learn J earlier." which may be a typo, but still... | | > You can learn all the important parts of array-oriented | programming with J and use actual words to do it. | | J doesn't use actual words. It uses symbols just like APL. In | fact, APL uses proper words or abbreviations for utilities | things that are not part of the core language, whereas J just | uses numeric codes combined with more glyphs. However, J is | ASCII-only (and uses bi- and even tri-glyphs) where APL uses | pleasant and mnemonic Unicode single glyphs, so you don't need | to parse which adjacent ASCII symbols form a "word". | codeflo wrote: | I'm not sure if it's common knowledge that "ur-" means | "original". | OkayPhysicist wrote: | In academic literature, "ur-" doesn't just mean original, as | much as it means "essential essence of" or "fundamental". In | contexts where you're talking about the first/original thing, | or something that provided characteristics that would | eventually become a trend, "proto-" would be more | appropriate. | | For a famous example, Umberto Eco's essay "The Ur-Fascist" | isn't describing what the first or original fascist movement | was, but instead exploring what makes Fascism Fascism. This | usage seems to be pretty consistent across academia, who | engage in the vast majority of cases of slapping foreign | prefixes onto English words. | Grieverheart wrote: | I hadn't come across the this before, but in Dutch we have | the oer- which is spelled out as in poor, so I somehow | connected the dots. | seanhunter wrote: | Years of bitter personal experience have taught me that FORTRAN | is the real ur-language in the sense that a suitably determined | programmer can write FORTRAN code in just about any language. I | have certainly had to debug this code all over the place. | lamontcg wrote: | Does this make Perl a FORTRAN? | seanhunter wrote: | I have unFORTRANned thousands of lines of perl code in my | time. | Will_Parker wrote: | I also think a lot of programmers could get a sort of | enlightenment by getting very proficient in SQL. (To the point | where you can do general programming in it using recursive CTEs | if you have to, even though probably impractical for real use | cases.) | OskarS wrote: | Pretty excellent summary, this is roughly the taxonomy I have in | my head. | | I would maybe add SQL as an ur-language as well. It's not quite | general purpose like most of these, but it should have a place in | this list, I think. It has some kinship with Prolog and the | declarative style, but it's really it's own thing. | | You could also maybe argue for something like LabView. Many | programmers look down on purely graphical programming languages, | but with Houdini, Unreal's Blueprints and the various node-based | shader/material systems in gamedev, I think it probably deserves | it's own little branch of this family tree. | Will_Parker wrote: | > SQL | | And, not to put too fine a point on it, being extremely | proficient will give you a massive competitive edge in the | industry. | marcosdumay wrote: | SQL is on the same group as Prolog. In fact, it is a simpler | and purer implementation of a constraint-solving language, so | it is probably a better option for learning the group than | Prolog. | | For the signal transformation ones, there are also the hardware | definition languages on the same category as LabView and | animation languages. | ucarion wrote: | To your point, Berkeley's intro-level CS class, CS61A, used | to use teach Prolog as an example of logic programming. They | use SQL now instead. | | I can't really attest to whether that's a better choice for | learning logic programming, though. It's easier to "run | programs" in Prolog. SQL wants to be a cog in a machine where | Prolog is more freestanding. | tonyarkles wrote: | I definitely did a bunch of Prolog in my CMPT216 class back | in undergrad and I hadn't really thought of SQL as an | alternative until today. I agree with you it's easier to | "run programs" in Prolog, and a lot of the concepts from | the class would have been more difficult to map to SQL than | Prolog (e.g. writing a Sudoku solver in Prolog was mind- | melting in a good way, writing a Sudoku solver in SQL would | probably be mind-melting in a bad way). The one thing that | SQL does have going for it though is that there's a ton of | tooling for getting practical real-world data into it. | | I would absolutely love to take a set of logic/set-oriented | problems and solve them both in Prolog and SQL, just to see | which ones are ergonomic in each language. Maybe this | summer at the cabin... | ucarion wrote: | The tooling thing goes both ways. I remember classmates | struggling with homework because they were trying to use | a different flavor of SQL than the SQLite we ran for | class. This stuff is obvious to engineers, but very | confusing to someone whose first hello-world was 8 weeks | ago. | ngruhn wrote: | SQL has no recursion. I would argue that's a pretty | fundamental aspect of Prolog, so I don't think SQL is a | representative replacement. | marcosdumay wrote: | Oh, it's certainly not a "type specimen". It does actually | have recursion and matching-like behavior, but those are | convoluted and not really used, so it is not very suitable | for general programming. | | But lacking those general features makes it an even purer | "learning example" of the group. | curiousllama wrote: | Yes it does. It's a fun problem to make a sudoku solver | | https://technology.amis.nl/it/solving-a-sudoku-with-one- | sql-... | ngruhn wrote: | Ok fair enough. I suspect that's a pretty non- | standard/rarely-used feature though. If you learn SQL you | likely won't encounter this and I still contest the idea | that SQL is a good entry into the logic paradigm. | | SQL and Prolog are both relational. That's very unique to | both. But SQL is all about querying databases. Prolog can | also be used and understood as a database querying | language but it's also very strong for | | - parsers | | - interpreters | | - expert systems | | - solving combinatorial problems | | If you really want to you can probably use SQL for that | too. Or any language for that matter. But going out and | learning SQL won't naturally expose you to these | applications and how well the logic paradigm lends itself | to them. | castorp wrote: | > I suspect that's a pretty non-standard/rarely-used | feature though. If you learn SQL you likely won't | encounter this | | Recursive common table expressions are part of the SQL | standard (since 1999) and are quite frequently used to | traverse hierarchical data (aka "adjacency list"). | | It is part of basically all (good) SQL tutorials - at | least in the "advanced" part. | blowski wrote: | I don't remember using recursion in a real project, but I | built a HN clone on top of Postgres, with the following | query: WITH RECURSIVE thread(id, | parent_id, user_id, post_id, timestamp, text, depth) AS ( | SELECT id, parent_id, user_id, post_id, timestamp, text, | 0 FROM comments WHERE user_id = 1 | AND parent_id IS NULL UNION ALL | SELECT c.id, c.parent_id, c.user_id, c.post_id, | c.timestamp, c.text, t.depth + 1 FROM comments | c JOIN thread t ON c.parent_id = t.id | WHERE c.user_id != t.user_id ) SELECT * | FROM thread ORDER BY timestamp ASC; | NoToP wrote: | Sql is accidentally general purpose. Recursive queries, a | feature present in all implementations since the 90s, put it | just over the line of turing completeness. | 0x445442 wrote: | I think you're first instinct is correct given libraries like | Linq and GQL in Groovy. The relational algebra is decidedly | different versus say map, filter and reduce. | davidw wrote: | SQL might be in its own category or not, but it shares a trait | that languages in other categories ended up with: "I know, | we'll make it kind of like writing English so that people who | aren't experts can program!". | | This is one of those things that seems to keep coming back - | recently in the Ruby world with Cucumber. | Animats wrote: | I suspect that idea is now dead. Anything new that accepts | something that looks like natural language now needs to be at | least as smart as ChatGPT. Stuff that sort of looks like a | natural language but is really a formal language now comes | across badly. | | There have been very few non-English programming languages. | There was a French version of COBOL once. I'm surprised that | something hasn't come out of China. There's a Chinese dialect | of Python. Does anyone use that? | blowski wrote: | Articulating your specification in precise language is the | hard part. Learning syntax is easy. | davidw wrote: | I always like to think of Captain Kirk speaking SQL to the | computer in Star Trek: COMPUTER, SELECT | COURSE WHERE MINIMAL PROBABILITY OF KLINGON ENCOUNTER | camtarn wrote: | Not to mention the various graphical programming languages used | in industrial control - ladder logic, continuous function | chart, and sequential function chart. Ladder in particular is | incredibly widespread, as it was a direct descendant of the | diagrams used to document and debug relay logic, and was | adopted in some of the first PLCs (programmable logic | controllers) in the late 60s/early 70s. | | Programming PLCs sometimes feels like going to, say, Australia | or New Zealand, and being immersed in an environment which went | down a different evolutionary tree very on in its development. | gumby wrote: | An article like this is hard to write. This is a good one. I have | a few quibbles, but they are just quibbles. | | IMHO* a distinguishing feature of Algol like languages (aka | "procedural" languages) is the distinction between expressions | and statements. Though personally I've never seen the appeal, | that distinction seems to be popular for some reason. | | * this isn't even a quibble -- the article is fine without it. | Just something that has always seemed weird to me. | codeflo wrote: | I'm not sure I fully agree with that characterization. Many | people would intuitively classify assignment as a statement, | yet it's an expression in C, which is fully in the Algol | tradition. And Rust is certainly a descendant of C, but blurs | the lines a lot further with loops being expressions. | jgilias wrote: | Rust is certainly a descendant of ML. It just adopted curly | braces to make it more palatable to C-ish people. | | https://doc.rust-lang.org/reference/influences.html | colonwqbang wrote: | Rust is a strict, GC-less Haskell but with a simpler type | system and a more complicated syntax :) | CyberDildonics wrote: | If you count the quibbles how many quibbles would there be? | gumby wrote: | To use si units, a small handful of quibbles. | scythe wrote: | In the case of Lua, the expression/statement distinction allows | the language to be completely whitespace insensitive with no | delimiters. The Lua grammar top level rule is just Stmt (ws | Stmt)*. I think Ruby might work similarly, but I don't | remember. | | C is less particular about the expression/statement | distinction. Java enforces redundancy. | weatherlight wrote: | There is no difference between expressions and statement in | Ruby (a descendent of the Agol Family). Everything evaluates to | a value so everything is an expression. | | (to be fair, it took a lot of inspiration from Smalltalk and | LISPs) | jimbokun wrote: | I would place Ruby in the Self/Smalltalk family, as it's | semantics are more similar to those languages. | fanf2 wrote: | ALGOL 68 and Rust are expression-oriented languages. | programmer_dude wrote: | The distinction in ALGOL, Pascal etc. is useless. | | But if you change your definitions such that expressions always | evaluate to a single value and do not have any side effects | while statements produce some kind of side effect (and may or | may not yield a value), the distinction becomes important. | | Especially if you believe side-effects need special handling | (i.e. you are a functional programmer). | Joker_vD wrote: | It's been done in some Pascal descendants: functions were | required to be pure but procedures were allowed to mutate | global state. Some even went as far as to remove functions | altogether (with quite unpalatable results). | colonwqbang wrote: | The only popular language I can think of that requires side | effects to be declared is Haskell. Which doesn't have a | distinction between statements and expressions. | | Are there any good examples of languages that have it, where | it isn't "useless"? | ModernMech wrote: | Might add Lucid in here as a dataflow ur-language. | garbagecoder wrote: | Objective C is a good example of a Smalltalk derived language | that was in heavy use for a while. Even though it's technically a | superset of C, in actual use it's more like a message passing | language. | svachalek wrote: | It's really Smalltalk and C pasted together with hardly any | mixing, like JSX=JS+HTML. I can't see how you could put it in | either column, it's absolutely in both. | garbagecoder wrote: | You're right, of course. It absolutely is and so it might be | a bad example, but it might be one where more readers would | be familiar with. | horeszko wrote: | >Every programmer needs to know a language in the ALGOL family | well. Once you do, then it's worth branching out. Learning a new | language that traces to an unfamiliar ur-language each year will | pay dividends | | I second this. I would consider myself an intermediate level | programmer and learning Scheme (via the excellent book "Structure | and Interpretation of Computer Programs") took my programming to | a new level and made me think of programming from a completely | different angle. | neallindsay wrote: | I think this taxonomy is interesting, but I have some quibbles on | the characterization of the languages I use the most. | | If I were to put Ruby into one of these categories, I would place | it first under Self (the object-oriented languages). Ruby is the | _most_ object-oriented language that I 've ever used in that | everything is an object that you send signals to. Even classes in | Ruby are objects (they are instances of the `Class` class). Ruby | was explicitly inspired by Smalltalk, one of the two exemplars | cited by the post. | | After the "Self" category, Ruby would fit better under the "Lisp" | family than the "ALGOL" family because of Ruby's deep | metaprogrammability. | | I'm guessing the author was fooled by the availability of C-style | `for` loops in Ruby, but that's generally not how Ruby | programmers write a loop. It's much more common to write | `list_of_things.map {...}` or use any number of other iteration | methods available through the `Enumerable` module. | | JavaScript to me fits better under the ML (functional languages) | family than "ALGOL". The first-class nature of JavaScript | functions is the core feature of the language. Of course, if you | define "functional languages" by having static type systems this | grouping wouldn't work for you. But for me it's all about the | functions. You can pass functions around and return them from | other functions. You can write utility functions to memoize or | otherwise transform functions. | | And while not _everything_ in JavaScript is an object the non- | object values in JavaScript have "object" versions. JavaScript | still has some object-oriented chops. Functions are themselves | objects, and while method calls are usually just reading a | function off of an object and calling it, you can intervene in | the property-reading step to enforce a more "message passing" | style. | | I'm guessing that most developers will have similar quibbles | about the categorization in this article of the languages they | are most familiar with. But this is still an interesting frame of | reference. And if you only work in languages that fit squarely in | the "imperative" category (or write code in an imperative way), I | encourage you to explore some of the others. | spankalee wrote: | _Lots_ of languages fit in the ALGOL + Self category - probably | most of the popular languages today. | | That's fine, this isn't actually a taxonomy, these ur-languages | are the progenitors of concepts and techniques. Of course they | can blend in decedents. | JW_00000 wrote: | I agree with your characterization of Ruby as a Self/Smalltalk | category language. (Or, a language with an ALGOL-style syntax | and a Smalltalk-style OO system.) | | > After the "Self" category, Ruby would fit better under the | "Lisp" family than the "ALGOL" family because of Ruby's deep | metaprogrammability. | | I don't agree with this: Lisp's metaprogramming capabilities | come from its macro system, while Ruby's metaprogramming | capabilities are due to metaclasses (which is exactly why it | fits in the Smalltalk category). | | JavaScript is also not a ML-style language in my opinion. ML- | like languages have not just types, but also pattern matching | and algebraic data types. First-class functions is not unique | to the ML category, it also applies to the Lisp and Smalltalk | categories (and maybe APL, I don't know it enough). | | I also still think of JavaScript as an ALGOL-style language | augmented with Self concepts (Self, not Smalltalk!), but this | may be because when I first started with JavaScript it didn't | have classes yet. The good old days... | lispm wrote: | > I don't agree with this: Lisp's metaprogramming | capabilities come from its macro system, while Ruby's | metaprogramming capabilities are due to metaclasses (which is | exactly why it fits in the Smalltalk category). | | Though, see the Common Lisp Object System Meta Object | Protocol (CLOS MOP). There were a bunch of meta-object | systems for Lisp, with the CLOS MOP as the most prominent | example. | neallindsay wrote: | I think of "functional" meaning first-class and higher-order | functions, but lots of people use that term to mean pattern | matching and type systems. It definitely seems like the | author of this article meant the "ML" category to mean the | latter. | | When they added the `class` keyword in JavaScript it didn't | change the capabilities of the language--it's still | prototypal under the hood, but I guess the syntax matters. I | certainly see people writing "classes" in JS a lot more now. | fanf2 wrote: | ALGOL 68 has first-class and higher-order functions. | Arguably ALGOL 60's call-by-name allows you to do some | higher-order things, even though its functions are not | first class. | aleph_minus_one wrote: | Where does Excel fit into this classification? | | ;-) | fzeindl wrote: | I'd add probabilistic languages like Figaro. | jleyank wrote: | It is sort of angels dancing on pins but who came first between | cobol, Fortran and Algol is curious. Even this article seems to | be putting Algol afterwards. It was a more collective language, | but I didn't see it penetrate as much as remain a discussion | topic. Perhaps the thread through C gave it entrance? | | And then there's basic.... Maybe that is just pidgin, giving | those who could not speak at all some words? | surprisetalk wrote: | I've always considered Fortran to be the "first", but with some | quick research, it looks like Algol was the first C-like lang | to add an if/then statement. My guess is that the author was | trying to approximate modern imperative programming. | | [1] https://craftofcoding.wordpress.com/2021/01/11/why-algol- | bes... | AnimalMuppet wrote: | Fortran was the first compiled language, that is, the first | language at a level higher than assembler. But Algol was a | block-structured language in a way that Fortran wasn't, and | virtually all languages of that "group" are block-structured | today ("goto considered harmful" and all that). So Algol is | more appropriate as the "prototype" of what exists today. | bloak wrote: | Mercury Autocode is perhaps a "missing link" between | assembler and Fortran, though I'm not sure of the dates and | whether the people developing Fortran knew about Mercury | Autocode. Things developed quite fast in the 1950s. | codeflo wrote: | Ruby is mostly a Self in this classification, right? Or maybe a | Self/ALGOL hybrid. It does have iteration as a method (.each), | but also has traditional if statements. | jewel wrote: | Ruby's if statements are actually expressions, they behave the | same as the ternary operator : ? foo = if bar | 1 else 2 end | Mesopropithecus wrote: | To some extent yes, it's certainly influenced by Smalltalk. I | just wish the author hadn't focused that much on control flow | in that paragraph. Ruby afaik also supports live programming up | to a point (REPL), but it's still not the same live-ness as in | Self or Smalltalk. | ThinkBeat wrote: | I think mentioning Simula would be fair. The first object- | oriented language. | | "" Simula (1967) is generally accepted as being the first | language with the primary features of an object-oriented | language. It was created for making simulation programs, in which | what came to be called objects were the most important | information representation. | carapace wrote: | Pretty good, but I would lump ALGOL, Lisp, and ML together as | Lambda Calculus languages. | Scubabear68 wrote: | I feel like C++ needs to go into its own category, seemingly | infinite features with only thinly veiled illusionary safety. | Mesopropithecus wrote: | Not a fan of snarky comments generally, but this one made me | laugh. And cry. | nerpderp82 wrote: | I despise this writing style. What is the point the author is | trying to make? Define what a ur-language is up front, don't be | so damn coy. This isn't much more than a list of interesting | languages for some definition of interesting. | joatmon-snoo wrote: | It's talking about different families of programming languages, | much like how we classify the different languages that people | today speak[1]. I definitely got thrown off by the choice of | terminology, but it makes sense once you go through the list. | | [1] | https://www.theguardian.com/education/gallery/2015/jan/23/a-... | nerpderp82 wrote: | The reader shouldn't have to reverse engineer a document! | | https://en.wiktionary.org/wiki/ur- | | Jesus! I thought these navel gazing low effort language posts | went out of favor in 2012. | | I know all of these languages and Forth isn't foundational | for anything we currently use, maybe the JVM because it has a | stack if you really try and torture the definition. It is | just a collection of languages so the author can look smart. | | If they wanted to provide insight, they would demarcate how | the semantics of computation are different from each of these | languages. It doesn't even mention the power of Forth in | being able to extend the language and runtime from within the | language itself. | | I'll see myself out. | slavapestov wrote: | There's a missing "minimal language" with a combination of | features that doesn't yet exist, but should: | | - value semantics with both implicitly-copyable and move-only | values | | - unboxed generics with type classes/traits/protocols and | associated types | | - as little syntax and sugar as possible for everything else | rileyphone wrote: | Maybe Austral? | | https://austral-lang.org/ | mlochbaum wrote: | The first point jumped out to me as contradictory: for | immutable values copying is only an implementation detail. | Apparently "value semantics" can also refer to mutable values | with exclusive ownership, is that the idea here or something | else? | slavapestov wrote: | > Apparently "value semantics" can also refer to mutable | values with exclusive ownership, is that the idea here or | something else? | | Yes, that's what I meant here. | Rochus wrote: | Well, a bit arbitrary, especially the choice of Self as the "ur- | language" of object oriented programming. | iainmerrick wrote: | I thought the choice of Self was a bit strange too, but if you | replace it with Smalltalk, the overall categories are pretty | reasonable. | cratermoon wrote: | Yeah, I'd have to go with Simula/Simula 67 as the OO ur- | language. | vidarh wrote: | I'm ambivalent about that. As a technicality and inspiration | it makes sense, but having learnt Simula (I studied in Oslo; | it was the introductory language for many years) it does not | give you the same focus on objects as Smalltalk does. But if | you want to put another language than Smalltalk as the OO ur | language, I'd certainly pick Simula over Self. | Rochus wrote: | Simula 67 is much closer to the mainstream OO concepts we | see in C++, Java, C# and Python than Smalltalk, or let | alone Self. ST was the first dynamically typed OO language | (scripting language actually) though. | vidarh wrote: | Ii is, because it inspired both the Smalltalk branch | _and_ the more mainstream OO languages, and hence it | makes sense to consider it as a possible ur-language in | that sense. | | Smalltalk is a branch, but it's an important enough | branch introducing important enough new concepts that | unlike with Self I wouldn't have an issue with people | considering Smalltalk it's own ur-language, and because I | agree with you that Simula at least on the surface will | seem more familiar to people familiar with ALGOL-derived | languages with OO mechanisms than to Smalltalk. | | Self, on the other hand, is less important for its | concepts (ok, so it has prototypes instead of classes, | but classes in Smalltalk are also objects, so I don't buy | that it's that conceptually different, especially in a | dynamic language where you can dynamically instantiate | and mutate classes) than it is for the papers on its | _implementation_. | Rochus wrote: | > _introducing important enough new concepts_ | | What do you have in mind, apart from duck typing? | | > _considering Smalltalk it 's own ur-language, and | because I agree with you that Simula at least on the | surface will seem more familiar to people familiar with | ALGOL-derived_ | | For ST we have to differentiate the 72 and 74 from the 76 | and later versions. Starting from 76 it has inheritance, | compiled methods and virtual method dispatch quite | similar to (though less efficient than) Simula 67. | vidarh wrote: | > What do you have in mind, apart from duck typing? | | The focus on message passing and late binding combined. | "Duck typing" is seriously diminishing it. You can write | code that appears that way even in C++ with RTTI and | inheriting from a shared root class and heavy use of | virtual. But to achieve the equivalent of the combination | of message passing and late binding in a language like | C++ not built for it you typically end up having to build | your own message dispatch machinery with no syntactic | support to make it cleaner that will make your code look | fundamentally un-idiomatic, and so doing so is tends to | be limited to specific problems. | | It's this combination that makes Smalltalk-derived | languages feel different. | | > For ST we have to differentiate the 72 and 74 from the | 76 and later versions. Starting from 76 it has | inheritance, compiled methods and virtual method dispatch | quite similar to (though less efficient than) Simula 67. | | I'd argue when we say Smalltalk without qualifying it, | most of us will be talking about Smalltalk-80. | Rochus wrote: | > _message passing and late binding combined. "Duck | typing" is seriously diminishing it_ | | Actually even ST-72 made synchronous calls, but at least | with a token stream interpreted by the receiving object | (thus at least a bit of "message passing"). In ST-76 and | later versions "message passing" is just nomenclature | used by the ST folks for something that is just ordinary | method dispatch and call (if you have doubts, you can | analyze the innards of the ST-80 VM yourself e.g. with | these tools: https://github.com/rochus-keller/Smalltalk | ). The major difference is the dispatch based on | signature hash (similar to e.g. Java interface method | calls) instead of static offsets, which enables late | binding (at the expense of performance); and since | everything including ordinary integers derive from | Object, all values and objects are subject to dynamic | method dispatch; it's no coincidence that Smalltalk was | the first language to be associated with duck typing. The | unification of scalar values and references, dynamic | typing, and likewise the minimal syntax where control | structures are implemented by means of runtime constructs | were already known from Lisp; also closures (i.e. ST | blocks) were already known before they were added to ST. | vidarh wrote: | > Actually even ST-72 made synchronous calls | | I've not suggested it is anything but synchronous, so I | don't know why you're bringing that up. It's not what | we're talking about when we talk about "message passing" | in this context. | | > In ST-76 and later versions "message passing" is just | nomenclature used by the ST folks for something that is | just ordinary method dispatch and call (if you have | doubts, you can analyze the innards of the ST-80 VM | yourself e.g. with these tools: | https://github.com/rochus-keller/Smalltalk ). | | Sure, you can implement method dispatch the same way. | I've written a (partial; unfinished; very buggy) Ruby | compiler that allows dynamic method redefinition with | even basic C++-style vtables. The point is not the | dispatch method but the ability to override them at will. | | > The major difference is the dispatch based on signature | hash (similar to e.g. Java interface method calls) | instead of static offsets, which enables late binding | | That late binding is an important part of it. | | But you don't even need to deviate from static offsets to | enable that late binding (you do need to do so if you | want the ability to do dynamic _interface-based | inheritance_ , but even then you can use a vtable-like | approach - see e.g. Protocol Extension: A Technique for | Structuring Large Extensible Software-Systems, M. Franz, | 1995 - which adds dynamic inheritance at runtime to | Oberon) as long as the dictionaries/vtables/whatever you | look them up in are mutable. | Rochus wrote: | Which closes the loop to my point, that Simula 67 is much | closer to the mainstream OO concepts we see in C++, Java, | C# and Python than Smalltalk, and there is no reason to | elevate Self (nor ST) as the "ur OO language". | vidarh wrote: | Which I agreed with you is a reasonable stance. To quote | myself: | | > Ii is, because it inspired both the Smalltalk branch | and the more mainstream OO languages, and hence it makes | sense to consider it as a possible ur-language in that | sense. | | I then went on to argue simply that because Smalltalk is | at the root of a significant branch, I wouldn't have an | issue with considering that an ur-language if one | considers that branch important enough and/or consider | message passing and late binding to be essential for a | language to be object oriented, as opposed to having some | object oriented features. | | But I went on to _again_ agree with you: | | > I agree with you that Simula at least on the surface | will seem more familiar to people familiar with ALGOL- | derived languages with OO mechanisms than to Smalltalk. | | To sum it up: I've argued that a reasonable case can be | made either for Simula or Smalltalk depending on how you | define OO, but that no well established definition of OO | would make Self a reasonable candidate. | vidarh wrote: | I had the same reaction. I think it stems from choosing an | extremely strict set of characteristics. If you take the | infamous Alan Kay quote [1], then e.g. Ruby fits in that | category. But with the characteristics as-is, the category of | OO languages as opposed to language that allow OO programming, | is near empty and it becomes easier to "get away with" talking | about the purity of Self rather than recognising that Smalltalk | has a lot of spiritual descendants, while Self is the basis for | a much smaller branch (Javascript being by far the most | prominent spiritual descendant, but even JS is ruled out by the | characteristics given). | | Ending up with Javascript and especially Ruby as ALGOL derived | makes no sense to me. Where more limited OO languages have | imported OO aspects, JS and Ruby have wrapped ALGOL syntax and | a few concepts around semantics that are much closer to Self | and Smalltalk respectively. | | [1] "OOP to me means only messaging, local retention and | protection and hiding of state-process, and extreme LateBinding | of all things". | golf_mike wrote: | So why is it called "ur"? | vaylian wrote: | Because most other languages descended from these early | languages. | thrill wrote: | That's the essence of the conversation here, isn't it? | CalChris wrote: | I've _never_ heard of ALGOL both predating and influencing | FORTRAN. FORTRAN was announced as a product at the Western Joint | Computer Conference in 1957 [1]. ALGOL was developed at a meeting | in Zurich in 1958 [2]. | | [1] | https://www.softwarepreservation.org/projects/FORTRAN/paper/... | | [2] https://en.wikipedia.org/wiki/ALGOL | adjav wrote: | ALGOL has certainly influenced the _development_ of FORTRAN at | least, with Fortran 90 and later fitting in pretty neatly | amongst the various ALGOL-likes. | nologic01 wrote: | Ahh this is good. But what are ur-languages really? Can we tell | when we have counted all of them? Is the collection determined | more by the application domain (the problems we think are | important to solve) or the architecture of Von Neumann type | computing)? E.g. I don't know much about quantum computing but I | suppose there is an ur-language associated with it. | | Whenever I see a taxonomy I itch for some underlying logic that | unifies them. If the explanatory scheme is successful then you | might actually convert the taxonomy into a tree, where the root | is some property that all of them ur-languages share etc. | hayley-patton wrote: | > A lot of work was done on how to make Smalltalk run fast and | efficiently, culminating in the Strongtalk project. | | The Strongtalk technology also came from Self; it was thought | that Self would be too hard to make fast, until it wasn't. | colanderman wrote: | I think reactive/synchronous languages [1] deserve a category of | their own. They share little/no overlap with any of the others. | My background in electrical engineering biases me to Verilog, | VHDL, and LabVIEW as exemplars, but there are many others. The | distinguishing characteristic of the category is that programs | are effectively declarative functions of time and can be composed | as such, much like electronic circuits. | | (I categorized the temporal declarative language TLA+ into the | Prolog family in another comment -- a main distinction here is, | though one can _express_ reactive relationships in TLA+, the | _intent_ of the language and design of the TLC model checker is | that such relationships are only usable for verification code, | whereas implementation code must be written as state-succession | pairs. A true reactive language permits and encourages both | styles of coding for implementation code -- e.g. Verilog 's = and | <= operators. Vice-versa, a true logic language includes | nondeterminism as a core construct, whereas reactive languages | typically do not.) | | [1] | https://en.wikipedia.org/wiki/Synchronous_programming_langua... | bee_rider wrote: | My education was in EE but I switched over to programming ASAP. | So my take on Verilog/VHDL is, like, super uninformed/perpetual | honeymoon/starry-eyed. But it always seemed to me that these | HDLs, since they fundamentally are pretty low-level and | asynchronous, if translated to assembly somehow, ought to | expose a ton of instruction level parallelism. | colonwqbang wrote: | "Asynchronous" not the right word since "synchronous" in | hardware typically refers to clock signals. | | The parallelism in hardware is indeed extreme. Like if every | line in your program ran at once, and then repeating every | clock cycle. | eschneider wrote: | Verilog/VHDL isn't so much a programming language as a hardware | definition language and woe to anyone who conflates the two. | Verilog/VHDL is it's own class of thing and sits outside of | software languages. | dgacmu wrote: | Without weighing in on exactly if it is or isn't a | "language", I think VHDL/verilog absolutely have a place in | the list and are a fantastic thing for (some, particularly | lower-level interested) programmers to learn precisely | because it's such a different way of thinking about | programming and huge piles of heterogeneous behavior | happening concurrently. It really cooked my head for the | first week or two and I think I came out the other side | better. (I hated writing VHDL with a passion. It was painful | medicine for a software person used to algol-style languages. | But I'm really glad I did.) | colanderman wrote: | They're languages for descriptions of reactive dataflow. That | they happen to specialize in dataflow which is synthesizable | as hardware doesn't change that they're programming | languages. | | (Yes, it's easy to accidentally write unsynthesizable code in | them -- but similar issues hold true for many declarative | languages.) | denotational wrote: | This is an overly simplistic take in my opinion. | | From a PLT perspective they are programming languages just | like any other, and one can analyse them using the same | machinery (formal semantics, typically of the operational | style) as any other programming language. | | Just because they are not even close to an imperative | paradigm doesn't make them any less of a programming | language. They are reasonably close to process- | calculus/message-passing languages in the sense that you can | treat a Verilog process as a receiver listening to channels | that contain messages generated when nets/variables are | driven. | | I agree that a software developer who tries to write Verilog | as if it were C will very quickly run into trouble, but that | isn't because it's not a programming language; it's because | it's a programming language with a similar syntax to C but | with drastically different semantics. | sebstefan wrote: | Which category does Coq go in? | | https://github.com/coq/coq | | With code example: | | https://github.com/coq-community/coq-100-theorems/blob/maste... | AS37 wrote: | ML | codeflo wrote: | Once you recognize the patterns, it seems clearly in the ML | tradition. Some bits and pieces look exactly like Haskell at | first glance. | navaati wrote: | Oh it's a ML alright, fits right next to Agda for example. | yread wrote: | another ur language that could be added is Spin or other formal | verification tool or LTL-based language | Nevermark wrote: | > A reader pointed out to me that getting Forth in a deep way | usually involves building Forths, since they're small enough for | a single person to build one from the ground up fairly quickly. | | I would say the same about Lisp. | | In fact, each list in Lisp is like its own little stack in Forth. | Prepending an element to the front of a list is like pushing onto | a stack. Separating the first element from the rest of a list is | like popping from a stack. | | Lists of lists & atoms are like stacks that can contain | references to other stacks, as well as atoms. | yellowapple wrote: | Interesting to see Erlang mentioned in the Self category instead | of the Prolog category, but it makes sense given how much it | borrows from both. | todd8 wrote: | The comments here are interesting, lots of possibilities for | other ur-languages. My suggestion is macro based languages. Macro | based programming predates all programming languages other than | ASM[1]. The simple macro systems, like early assemblers provided, | aren't ur-languages, but once macros can expand other macros and | generate definitions of new macros, the macro systems can become | general purpose programming systems. | | The two earliest macro systems that were clearly designed to be | general purpose languages that I know of are Christopher | Strachey's GPM[2] and Calvin Mooers TRAC[3] programming language. | These languages appeared at roughly the same time, the mid 1960s. | I prefer the syntax of TRAC, but otherwise they are almost | isomorphic. TRAC was featured in _Computer Lib /Dream | Machines_[4] by Ted Nelson where the author said it was one of | the three important languages for programmers to learn. A good | introduction to TRAC and it's implementation can be found in | _Etudes for Programmers_ [5]. | | Other more contemporary examples of macro programming languages | are m4, and TeX. LaTeX is programmed in the TeX macro system. | | [1] Daniel Weise and Roger Crew, "Programable Syntax Macros", ACM | SIGPLAN, 1993, https://dl.acm.org/doi/pdf/10.1145/173262.155105 | | [2] Christopher Strachey, "A general purpose macrogenerator," | Computer Journal, 8(3), pp. 225-241, 1965 | | [3] Calvin Mooers, "TRAC, a procedure-describing language for the | reactive typewriter", CACM, Vol 9(3), March 1966, pp. 215-219, | https://dl.acm.org/doi/10.1145/365230.365270 | | [4] Ted Nelson, "Computer Lib/Dream Machines", 1974, Self- | published. (There is a 2nd edition from Microsoft Press, but I'm | only familiar with the 1st edition). | | [5] Charles Wetherell, "Etudes for Programmers", 1978, Prentice | Hall. (It's out of print and available from Amazon for $427. I'm | going to have to start locking up my old books.) | t-3 wrote: | Macro/concatenative languages should replace the Forth line. | The author is off-base in thinking RPN or stacks are important | to Forth rather than concatenativity. RPN is just an easy way | to make interpretation simple, an implementation detail, not a | functional requirement. It would be like defining APL as being | evaluated right-to-left. | pulvinar wrote: | The stack is important to Forth, but equally so is its | threaded-subroutine-call nature, which isn't present in other | early languages that I know of. That puts Forth halfway | between assembly and higher-level (and easier to read) | languages. I never saw it as a macro language. | | At least that's the viewpoint I'm familiar with from back | when we heavily used it. | turndown wrote: | What do you mean by threaded here? | mikevin wrote: | > What do you mean by threaded here? | | Here's a good explanation. | | https://www.bradrodriguez.com/papers/moving1.htm | jasonwatkinspdx wrote: | https://en.wikipedia.org/wiki/Threaded_code | | It's a way of structuring an interpreter. In forth a word | is just a pointer to its definition, which in turn is | just a list of pointers to other words, potentially user | defined or built in primitives. Execution threads through | these pointers, much like making subroutine calls with | arguments being passed implicitly on the stack. | | It's much more compact and lower overhead than a classic | interpreter walking a full Abstract Syntax Tree | structure. These days most languages are going to a full | native code JIT however. | nerpderp82 wrote: | The last two books are available at your favorite site. | jazzyjackson wrote: | I read about TRAC in Computer Lib while working on a template | language that basically just has #! as a special prefix in JSON | objects to signal a macro-expansion. I expand macros until | there are no more macros to expand, and return that as the | result to render in HTML. Reading about TRAC is what made me | realize I had a general purpose language on my hands. Too bad, | I could have avoided the whole exercise of writing an | interpreter, scheduler, debugger if I just left it as an | alternative syntax for interpolating variables into HTML. | | Thanks for the tip on Etudes for Programmers, looks like I'll | be able to look at it in a library at least, surprised | archive.org didn't have it. | KingLancelot wrote: | [dead] | chunes3 wrote: | I take issue with calling stack languages the inverse of Lisp. | This isn't really the case since functions in stack languages are | fixed arity, while Lisp functions are not. The inverse of RPN | would be the fixed-arity prefix notation used by the REBOL family | of languages. | netbioserror wrote: | Very useful for an intermediate programmer who appreciates the | craft and wants to extend their skills by becoming a true | polyglot. | | As for total beginners, it can be demeaning to explain why asking | which language of the ALGOL descendants to learn is a pointless | question. For their case, I don't bury the lead: I tell them | "They all have the same lineage and are fundamentally similar, so | just pick the one you'll learn the most robustly with. Most | everything else is learning libraries." | umanwizard wrote: | > Lisp is about a year younger than Fortran, which makes it the | second oldest language still in use today | | I disagree with this line since Lisp is not really a "language", | but a family of them. If we consider Clojure and original Lisp to | be the same language, we should also consider that to be true of | Algol and Rust. | lispm wrote: | The original LISP was a language and its implementation. It was | also documented - see for example the LISP 1 manual and other | publications about it. From that a series of languages evolved, | which shared the original core (syntax, data structures, | operators, ...) That's what I would consider the core Lisp | language family. Most of these languages will have 'Lisp' in | its name. | xrayarx wrote: | Where does TLA+ and PlusCal fit in? | | They do not match any of the listed families, do they? | colanderman wrote: | PlusCal is very much in the ALGOL family (with the extension of | nondeterminism, which is needed to serve its purpose of | verification). | | TLA+ is similar to Prolog, extended with a next-state operator | and the temporal operators (again, to serve its niche purpose). | | (Though the main TLA+ implementation, TLC, doesn't implement | logic variables as richly as Prolog does, so coding style | within a relation tends to be almost a bit more imperative. | They exist in the language though, via the unbounded [?] | operator.) | hwayne wrote: | TLA+ and PlusCal are specification languages, not programming | languages. Spec languages have their own ur-languages: TLA+ is | from the LTL dynasty, Alloy and Event-B are from Z, PRISM is | CSP I think? | colanderman wrote: | Respectfully (you having literally wrote the book!) I | disagree that there's a strong difference between | specification and programming languages -- and specifically I | feel that the "gap" between verification and implementation | can be filled by recognizing this. | | To take TLA+ as an example -- I've certainly written (short!) | programs in both TLA+ and PlusCal -- both imperative | (typically an implementation of something that I'm modeling) | and declarative (to solve logic problems in the same manner I | would use Prolog). | | And there's nothing privileged about TLC's capabilities and | limitations -- one could equally imagine a TLA+ interpreter | which disallows cross-state nondeterminism or use of temporal | predicates but allows interaction with the environment via a | special variable or predicates, without needing to augment | the language, thus allowing "normal" programs to be written | and executed. Or a TLA+ interpreter which permits full | nondeterminism via a SMT backend, which can act as a richer | version of Prolog. | | Imagine writing correctness-critical code snippets in TLA+, | verifying them, then compiling and linking them into an | application written primarily in another language! I don't | believe there is anything about TLA+-the-language which would | need to change for such a tool to exist. | | There are of course language elements _specific_ to | verification in TLA+ -- namely the temporal operators pose a | challenge to "synthesizing" an executable program. But I | don't think this makes TLA+ any less a programming language | than the existence of, say, Haskell's type language makes | Haskell a programming language. | | Verilog sits in a similar space, where it was designed for | verification, and is full of constructs usable only for | verification, but also has a "synthesizable" subset which can | be and is used expressly for implementation without involving | verification of any sort. Although one can argue Verilog is a | hardware description language rather than a programming | language, I haven't seen anyone argue Verilog is a | specification language rather than either of those. | hwayne wrote: | You raise good points! Ultimately the technical distinction | between a specification and programming language comes down | to the existence or not of a compiler. Imagine if Python | came out in 1960, but without anybody building a Python | interpreter. People would consider it a spec language. | | (Also, lots of spec languages are _weaker_ than programming | languages, to make verifying them easier. IIRC mcrl2, FDR, | and Promela all fall under this category.) | | I still think there are practical differences, though, | between a language designed for the purposes of | specification and one designed for implementing programs. | TLA+ has temporal predicates and cross-state nondeterminism | _because_ it makes modeling at a high-level easier, even | though it makes programmatic implementation harder. That | leads to different design decisions through the language. | | More importantly to the OP, thinking of them as | fundamentally different is useful because they draw on | different inspirations. It could be that PLs and SLs | converge later, but their origins and lineages are still | different. And that's interesting and worth studying. | | I don't think talking about ur-languages is as useful as | talking about archetypes: "ur-" to me implies "the | original", and that's a hard thing to do. TFA has some ur-s | like self that aren't the original, but still are useful as | archetypes. Off the top of my head, the archetypes of | formal speciifcation would be | | * Temporal Logic (LTL, CTL, TLA) | | * Relational algebra (Z, B, Alloy) | | * Guarded Command Language (Promela, SPIN) | | * Process Calculi (CSP, FDR) | | * Labelled Transition Systems (Petri Nets, mclr2) | | * Just drawing a diagram and figuring out the semantics | later (UML) | | * Abstraction over an existing programming language | | This is all real messy, and I see lots of overlapping | concepts and unclear cases. Are state machines their own | thing, part of LTS, or an implementation detail of the | specification approach? Should we be distinguishing between | the mathematical formalisms and the languages themselves? | What about the vaster world of specifying code and not | designs? etc etc etc | gjadi wrote: | Probably because they aren't programming languages in the sense | you won't produce a program = executable with it, but rather a | proof. | navaati wrote: | And yet Agda, which is a proof language, was included (in the | ML family). | | Looking at some TLA+ examples, I'd say, squinting a bit... | somewhere around Prolog ? I'd love to hear someone chip in ! | colanderman wrote: | Yes, having used both TLA+ and Prolog extensively, they | share many similarities (both having roots in first-order | logic). In practice -- TLA+ code is often a bit more | "imperative" owing to the fact that unbounded existential | quantification isn't implemented in the TLC interpreter | (whereas in Prolog, it is a core aspect of any | interpreter). | | And of course, TLA+ has a suite of temporal operators used | exclusively for declaring contracts in service of its role | for verifying specifications. Which (as @hwayne points out | elsewhere) stem from mathematics -- Linear Temporal Logic | specifically -- and not programming. | felixgallo wrote: | IMO the eighth ur-language is Erlang (with cousin Elixir), which | brings the ultra-scaling actor model, an abstract operating | system designed for high reliability and low latency, and a bunch | of nice rare features like builtin binary | structuring/destructuring and pattern matching. While it had its | origins in prolog, it's now sufficiently far away from prolog's | inner machinery that it only has syntactical similarity. | | Learning erlang made me definitely at least 10% smarter as a | programmer. Highly recommend, even if you never use it in anger. | yellowapple wrote: | I disagree that Erlang is an ur-language (it's too close to the | Self and Prolog ur-languages to be its own, IMO), but I do | agree that OTP/ERTS could be a sort of ur-framework or ur- | runtime, for exactly the reasons you describe: even explicit | attempts to implement "Erlang-style concurrency in $LANGUAGE" | routinely only cover some superficial "yeah we've got actors | that pass messages and _maybe_ supervise one another " without | covering preemptive multitasking, hot-reloading of functions, | distribution across nodes, and the myriad other features that | give Erlang its reputation for extreme fault-tolerance. | danabrams wrote: | That was my first thought, reading this. Although it's almost | like a combination of lisp, self/smalltalk and prolog, with OTP | being the innovation. | colanderman wrote: | Erlang is a nice and unique language, but I feel at its core it | falls into the object-oriented/message-passing paradigm, very | much in the vein of Smalltalk. Consider these paragraphs from | Smalltalk's Wikipedia entry [1]: | | > A Smalltalk object can do exactly three things: | | > 1. Hold state (references to other objects). | | > 2. Receive a message from itself or another object. | | > 3. In the course of processing a message, send messages to | itself or another object. | | Replace "Smalltalk object" here with "Erlang process" and the | description holds. | | > Unlike most other languages, Smalltalk objects can be | modified while the system is running. Live coding and applying | fixes 'on-the-fly' is a dominant programming methodology for | Smalltalk and is one of the main reasons for its efficiency. | | Erlang's famed robustness similarly owes much to its ability to | update code in a running program. | | [1] https://en.wikipedia.org/wiki/Smalltalk#Object- | oriented_prog... | davidw wrote: | Joe Armstrong talked about that in the past, and I can sort | of see it if I squint, but at the end of the day, there are a | lot of things in Erlang that are not processes, like most of | your basic data types, so I'd just say Erlang is good at | borrowing, like a lot of practical real world languages are, | and in doing so, came up with a niche where it's pretty good. | It takes things from the FP world, its syntax from Prolog, | and definitely has message passing as an integral part of how | you architect a system with it. | colanderman wrote: | Fair point! It definitely is a mishmash of good ideas. I | think the message passing / OO aspect stands out to me as | most distinct from other languages, even if it's not as | pervasive in the language as in Smalltalk. | tonyarkles wrote: | It's funny to me. OTP Processes have a ton of similarities | to Agents, but from what I recall it sounds like those two | things were developed almost entirely independently and it | wasn't until way after the fact when people outside of | Ericsson started using Erlang that people started noticing | and commenting on that. | OkayPhysicist wrote: | That got briefly mentioned in the Object-Oriented section. It's | worth noticing that the article specifically excluded Java and | C++ from that section, putting them in the Algol heading | instead. Smalltalk and Erlang share enough ideologically that | it seems reasonable to me. | kqr wrote: | I agree. Many of the core language concepts from Erlang you can | get from Self and Prolog, but experiencing the OTP is something | different that I think you only get from the Erlang family. | taneliv wrote: | Likewise, experiencing JVM is something different from ALGOL | ... | | And not quite sure if SQL could be grouped together with | Prolog due to its declarative nature. But if so, DBMS is, | like OTP, quite far from Prolog, just in a slightly different | direction :) | | I guess what I'm trying to say is that the list of ur- | languages seems quite fine to me. | paulddraper wrote: | I think there are additional examples, where the _syntax_ isn 't | necessarily wildly different, but the paradigm is | | * Shader code: is ostensibly C, but fundamentally different | runtime characteristics. | | * Dataflow (or Signals/Excel): Topological graph of computation. | | * HCL (or Cloudformation/CDK/etc): Connecting execution via a | different runtime. | | * React Hooks | | IDK it just seems like there is a lot. | rwmj wrote: | I think you could make a case for including Ada and/or COBOL, | separately from ALGOL. Ada is/was an early attempt to remove | errors from programming, and COBOL was an attempt to make a | "business language" that would be understandable by suits. | 7thaccount wrote: | Cobol or Mumps for sure. I think Ada is close enough to Algol | to not need its own category. | rst wrote: | The claim that Fortran and assembly languages "trace to" Algol | is... odd. Fortran I was released in 1957; the first fragmentary | spec for Algol wasn't released until 1958 (with Fortran project | leader John Backus as one of the primary contributors). And there | were also recognizable assemblers, in the modern sense, at the | time (although terms like that weren't always used with their | modern meanings in the 1950s, which lays up all sorts of traps | for the unwary). ___________________________________________________________________ (page generated 2023-05-04 23:01 UTC)