[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)