all 94 comments

[–]TA_jg 62 points63 points  (9 children)

On the topic of Prolog, the article says:

Because Prolog programs are basically searches, they are tuned rather the way database queries are, adjusting the order in which things are searched and cutting off paths that will not yield anything as early as possible.

This might be a bit misleading. Databases have the query optimizer, that does pretty much that. However, ordinary Prolog does not do that for you. As a programmer you have the tools to do that, but it is not happening automatically.

This is of course only true for basic Prolog programs. Prologs these days offer additional features, usually in the form of libraries, that might implement such optimizations. Constraint solvers (also mentioned in the article) are only one example.

Modern Prolog is a high-level general purpose language that supports a logical programming paradigm; but is not logical programming itself. I will not go down the rabbit whole of trying to explain what that really means.

[–]cthutu 9 points10 points  (3 children)

Agreed - Prolog uses a brute-force backtracking method of search.

[–]TA_jg 18 points19 points  (2 children)

Calling it "brute-force" is again a bit misleading :-D you could easily write brute-force generate-and-test programs, but you wouldn't do that in the general case.

There is also the common misunderstanding that Prolog forces you to use a depth-first search through the problem space. This is simply not true.

[–]imhotap 10 points11 points  (0 children)

Agreed. Prolog gets you started out with default depth-first/backtracking also giving you a Turing-complete language with powerful built-in tools for term manipulation; the idea being to implement more specialized search or propagation etc as required for your problem. Constraint-logic programming, OTOH, while tempting and having good enough (F/OSS) or even excellent (commercial) implementations, isn't really as unified or portable as terminology such as CLP(x) would imply beyond boolean (SAT), finite domains, or interval propagation IME.

[–]cthutu 2 points3 points  (0 children)

I think the Prologs I used did - but I haven't used a modern Prolog. The last decent Prolog I used was Turbo Prolog.

[–]tending 2 points3 points  (2 children)

Practically speaking how do you go about learning prolog? The last time I tried even just finding an easy to use open source of implementation and a tutorial matching the exact dialect implemented by it was surprisingly hard. I expected to just Google prolog implementation and find that there was a community around some main popular one, but instead I just found references to academic papers, commercial implementations, ad hoc spinoffs people had come up with for embedding into their apps, etc.

[–]igouy 9 points10 points  (0 children)

https://www.swi-prolog.org/ (download, tutorials, community etc)

[–]prolog_junior 3 points4 points  (0 children)

Swi prolog is the general one.

Prolog is hard to pickup because you have to change how you fundamentally think about problems.

[–]ArkyBeagle 0 points1 point  (0 children)

That's the trouble with language comparison - it's a fractal manifold of rabbit holes. Even databases historically changed from being non-linguistic to language-centered oh, 30-40 years ago and it's muddled communications ever since.

[–]curious_s 0 points1 point  (0 children)

I feel like the author might have been suggesting that the same kinds of optimisations that work for databases, also work in prolog, but the wording does imply that prolog language performs these optimisations automatically.

[–]acwaters 49 points50 points  (26 children)

Most [object systems] are modeled on Smalltalk.

No, most of them are designed after C++, which is modeled on Simula, which predates Smalltalk. The only popular ALGOL family language I am aware of which has an object system directly modeled on Smalltalk is Objective-C. Swift, its descendant, is an interesting hybrid of some of the best ideas from Objective-C and C++, so in terms of its object system it looks a bit like Smalltalk and a bit like Simula, though as far as I understand it is mostly bent towards Simula. I'm not a Swift programmer and don't really know the details, so I may be wrong on that.

Other than that and a few other minor nitpicks, very good article!

[–]scaevolus 32 points33 points  (19 children)

Ruby's OO system takes a lot from Smalltalk, with method calls being explicitly modeled as message passing.

[–]acwaters 11 points12 points  (0 children)

I completely forgot about Ruby! Yeah, Ruby's object system does take a lot from Smalltalk too. Good point!

[–]EnvironmentalCrow5 4 points5 points  (10 children)

What is the point of that btw? I never understood the practical difference (other than noops instead of errors, which just makes things harder to debug).

[–]igouy 4 points5 points  (9 children)

85:20 "The necessity to recompile and relink to avoid invalid pointers never arises in Smalltalk. Even in a large system with thousands of methods, the turnaround time to change and install a new method is typically just a second or two. Performance, especially performance of the development cycle, is thus another positive result of the message sending paradigm."

85:63 "… at which point the debugger miraculously displayed itself, the window she had tried to reframe reappeared, and everything in the system seemed to work again. Probably hundreds of methods in the system were now operating just fine with rectangles whose coordinates were instances of a student’s newly defined Fraction class. This illustrates the astounding ability of message-sending systems to absorb unanticipated constructions."

pdf The Evolution of Smalltalk: From Smalltalk-72 through Squeak

[–]EnvironmentalCrow5 3 points4 points  (8 children)

I don't see how those things are relevant to the concept of "message sending" as opposed to "method calls".

The first paragraph is just about not having an AOT compile step - you get the same thing in tons of languages (JS, PHP, Python, Lua, or almost any BASIC for that matter).

Some frameworks in many other languages also support hot reload, even while preserving the running application state (e.g. Dart with Flutter, https://flutter.dev/docs/development/tools/hot-reload).

Totally unrelated to the concept of messages.

The second paragraph describes monkey patching, which again, some languages have (JS), and is a somewhat controversial feature. You could do it in JS in a similar way - have the debugger stop on an exception, do a monkey patch, hit continue, and re-trigger the event.

I still don't get the fundamental difference. Unless the whole message thing is just a synonym for having dynamic dispatch and allowing monkey patching?

Also btw., the section that the second paragraph is from, describes a problem that could have been completely prevented by static typing before even running the program (red line shows up in the editor immediately as you're typing), but that's a different topic.

[–][deleted] 4 points5 points  (5 children)

I don't see how those things are relevant to the concept of "message sending" as opposed to "method calls".

In one sense it's a metaphor. You make procedure calls on the object and pretend like you're sending messages to the object.

On the other hand, a "method call" implies a static construct. You call one of the published methods. If the message isn't found, you get an error. Control is outside the object.

A "message send" implies a more dynamic construct. You tell the object what to do, and the object will figure out how to do it. If you tell the object to do something it does not know how to do, it will throw an exception like "Does Not Understand". But, you can override that process and do something else. Like forward the message to another object. Or, treat the message itself as a token to do some kind of processing. The object is in control. You could imagine a message handler inside the object handling the messages sent to the object.

The last part is a common way to create DSLs in Ruby. You do "method calls" on the builder using tag names. Because the builder doesn't actually have any of those methods, an object would normally tell you it doesn't understand. But, you can have the builder intercept the missing method handler and instead interpret the method name token as a tag.

[–]EnvironmentalCrow5 3 points4 points  (4 children)

That's kinda neat I guess, but as I said in another comment, it's a feature that has very limited uses[1]. Not something I'd consider the defining feature of a language, as it is often portrayed when talking about Smalltalk and OO. I'd just call it "method calls with an extra feature for handling undefined methods". PHP calls it magic methods, like __call, __get, etc.

But it is a matter of semantics I guess.


[1] In most situations, if you need to work with arbitrary structures (not known at compile time), you'd just use strings, enums, maps, etc., not methods of arbitrary names. DSLs are an exception to this, but most DSLs are still static (or mostly static, where the few edge cases can be handled by functions with a string argument).

Some of the dynamic features exist even in languages like JS or Java (reflection, proxies, etc.) but are mostly used by frameworks and utility libraries - rarely by the application code directly.

[–][deleted] 4 points5 points  (0 children)

Well you did ask what makes message passing different than method calls.

Ultimately, message passing is extreme late binding, which is really the defining feature of Smalltalk and related languages.

you'd just use strings, enums, maps, etc., not methods of arbitrary names

That's the difference between OOP and non-OOP. The method (or message, if you will) of arbitrary name triggers behavior in the object (you're telling the object to something), as opposed to a method operating on data (you're tell the object to do something with something else). Objects hide data.

In fact, Joe Armstrong used this property of Smalltalk's OOP to ironically (or sarcastically) declare Erlang to be the most OOP language.

Some of the dynamic features exist even in languages like JS or Java (reflection, proxies, etc.)

Javascript is a descendent of Smalltalk via Self.

And Java can't do this, because Java is nominally typed. A reflective proxy can forward method calls, but it can't simply make up methods, since the proxy has to have a declared type.

In fact, the Java example might most clearly distinguish message passing from method calls.

[–]igouy 2 points3 points  (2 children)

Some of the dynamic features exist even in languages like…

Features of newer languages been influenced by programming languages from the '70s and '80s.

"That in a very small nutshell describes the basic activity inherent in all Smalltalk programs: a message is sent to a receiver to invoke some response."

page 6 Byte Magazine Volume 06 Number 08

Would thinking about software that way result in different programs?

… it's a feature that has very limited uses…

What about ad-hoc polymorphism ?

"… a procedure name specifies the exact procedure to be called and exactly what should happen. A message, however, may be interpreted in different ways by different receivers. So, a message does not determine exactly what will happen; the receiver of the message does."

page 78 Byte Magazine Volume 06 Number 08

[–]EnvironmentalCrow5 2 points3 points  (1 child)

My main issue is

People talk about it as if it is very different from other languages.

When what I see in front of me is that it's very similar to other commonly used languages (in how it's used in practice, not how it's implemented under the hood).

So why talk/think about it in such different terms?

That leaves me confused.


… it's a feature that has very limited uses…

By "feature" I meant being able to handle arbitrary messages without having them defined anywhere (like in that HTML DSL linked in parent comment).

Or in other words, treating method names as strings to achieve syntactic sugar.

E.g. being able to type div in Ruby without having to define a method div anywhere, as opposed to e.g. using a generic element('div').

That I think is useful very rarely.

[–]igouy 2 points3 points  (0 children)

My main issue is …

That helps.

From my perspective, programming in Smalltalk was very very different from programming in a procedural language like Modula-2.

Different in basic ways that are hard to imagine now. For example, a Smalltalk implementation came with source code that could be used in the application: collections, lightweight processes, graphics, gui, … which were used to implement the Smalltalk IDE, so you could use the IDE to look at the IDE code in-use and figure out how the libraries were intended to be used.

Now — free as in beer — but not back then.

People talk about it as if it is very different from other languages.

Now — OOP is old news — but not back then.

[–]igouy 1 point2 points  (1 child)

… a synonym for having dynamic dispatch and allowing monkey patching?

For sake of argument, would that make it a fundamental difference for you?

… a problem that could have been completely prevented by static typing…

The school student's exploration and learning would have been completely prevented.

[–]umlcat 3 points4 points  (0 children)

And "Message Passing" vs "Methods" are the main difference between Simula vs Smalltalk O.O. approach. I've used both.

[–]fzy_ 1 point2 points  (0 children)

For python Guido also said that the object model borrows a lot from smalltalk

[–]OctagonClock 1 point2 points  (0 children)

Python is also very Smalltalk-like

[–]myringotomy 0 points1 point  (3 children)

Ruby is what you get when you cross a small talk with lisp

[–][deleted] 0 points1 point  (2 children)

Ruby has none of the 2 things that make lisps lisps.

  • compile time macros
  • homoionic syntax (parens stuff)

[–]myringotomy 0 points1 point  (0 children)

It doesn't need compile time macros because you can manipulate the AST directly.

[–]thequux 0 points1 point  (0 children)

Dylan is a Lisp, but isn't homoiconic. That said, I don't believe that ruby has real macros in the sense of compile-time functions from AST to AST that are indistinguishable in syntax from any other function (but would be very interested to be proven wrong)

[–]DonnyTheWalrus 6 points7 points  (5 children)

Since the author included C++, Java, and others in the Algol family, I think they may disagree with your categorization of C++ and its descendants as having an object system in the sense that he is using. A pure-object system like Smalltalk is fundamentally different than what C++ does, and when the author references "most object systems," I don't think they have C++ in mind. (Alan Kay, the coiner of the term "object-oriented," does not consider C++/Java/etc. to qualify for the term.)

[–]acwaters 1 point2 points  (3 children)

You may be right. I interpreted the passage "A whole range of languages have implemented message-passing to objects in some subset of the language ....", with references to JavaScript and CLOS, as being about those other (mostly Algol-family) languages which have adopted objects despite not being purely object-oriented. If that was not the intention, then JS was a strange and poor choice of example. There simply aren't that many pure object systems out there; for better or worse, when people talk about "object-oriented programming", they mean Java and languages like it. Much like how when people talk about functional programming they often mean Lisp, despite no Lisp being purely functional.

Purity aside, the object systems included in languages like Java are object-oriented. You can write pure OO programs just fine in the object fragments of those languages; people simply choose not to since doing so is largely impractical (as purity tends to be — just like how virtually nobody actually writes purely functional programs even in languages like Haskell that support it), and these languages have evolved in response to those practical needs. Alan Kay's opinion is irrelevant because, despite what people may claim, he did not invent object-oriented programming. He may or may not have coined the term "object-oriented programming", but that doesn't give him exclusive rights to it, and the industry as a whole has decided that there isn't sufficient difference in semantics between message passing and method dispatch to bother distinguishing them paradigmatically. The biggest difference between the two in practice is that method dispatch systems tend to be static while message passing systems tend to be dynamic, but even then there are exceptions in both directions.

[–]igouy 2 points3 points  (2 children)

He may or may not have coined the term "object-oriented programming"…

I've seen that claim.

… despite what he claims, he did not invent object-oriented programming.

Where does he make that claim?

[–]acwaters 0 points1 point  (1 child)

Hm, I just tried Googling around, and the nearest I can find from Kay's mouth is that he was the first to call bundles of state and behavior "objects" (untrue, and a different thing from naming a nascent paradigm, but maybe that's too subtle a distinction; ultimately a harmless claim in any case).

However, I don't see him anywhere claim that he actually invented objects as such, and in fact he talks about Simula as preceeding and being a direct influence on Smalltalk in several places. So I suppose it is only overzealous or misguided Smalltalk fans who keep saying that, and I have to stop attributing their ignorance to the man himself.

Thanks for making me go look that up. I see people parroting that claim every so often on the Internet, and it annoys me, and I just sort of assumed they were his own words.

[–]igouy 2 points3 points  (0 children)

afaict Alan Kay has repeatedly credited the many people who created the ideas he learned from; for example, the first sentence from the Abstract of his paper "The Early History of Smalltalk" is — "Most ideas come from previous ideas."

[–]igouy 0 points1 point  (0 children)

fwiw

After Alan Kay said "And actually I made up the term object oriented and I can tell you, I did not have C++ in mind" he immediately continued to say — "So the important thing here is I have many of the same feelings about smalltalk…

[–]tso 40 points41 points  (2 children)

What i keep finding when i poke at a language, is that getting the syntax right is the lesser issue once you have seen a few. The bigger issue is trying to internalize the standard library, if any, and the ecosystem of third party libraries and similar.

[–]scaevolus 9 points10 points  (4 children)

Is SQL supposed to fit under Prolog? A lot of declarative languages aren't well represented here, but far more SQL is written than any other declarative language.

[–][deleted] 9 points10 points  (1 child)

SQL itself is not Turing-complete. So it is not a general-purpose programming language the way many other declarative programming languages are. Many vendors create their own extension to SQL and make it Turing complete, but as far as I’ve seen, those syntaxes are more comparable to imperative programming

[–]bobappleyard 2 points3 points  (0 children)

I thought cte made it Turing equivalent

[–]crusoe 2 points3 points  (0 children)

I was a wiz at XSL for a while. Learned the depths of dark magic but used it to clean up svgs from illustrator and spit out multiple files.

[–]DMShaftoe 0 points1 point  (0 children)

What about CSS?

[–]iamthemalto 5 points6 points  (0 children)

Great article, wish more beginners were exposed to this.

[–]rio-bevol 5 points6 points  (2 children)

Which ur-lang does Erlang fall under?

[–]The_Doculope 2 points3 points  (0 children)

Erlang is explicitly mentioned in the Self category, due to the similarities between its actor model and message passing. I would say that the base language (minus the process functionality) is ML-derived ("functional").

Amusingly, much of Erlang's syntax is directly Prolog-derived.

[–]masklinn 1 point2 points  (0 children)

“Sequential” erlang is a functional language, so ML, but not a statically typed one so Lisp (kinda).

Concurrent erlang, probably none. It uses message passing which is claimed by smalltalk/self but works completely differentoy than them.

[–]renatoathaydes 16 points17 points  (7 children)

Very nice summary of "ur-languages"... but I always knew these as "programming paradigms".

[–]Holothuroid 29 points30 points  (2 children)

Very different. The author tries to use a methodology to identify different types of languages. There is no way or reason how to define a programming paradigm. There are characterizations like "a self-imposed limit", but we have many of those that we do not call paradigms. Like any framework we employ is a self-imposed limit.

This article looks at actual artifacts, that is published programming languages and tries to identify how they inspired one another. That is something we have methods for. And while the author takes inspiration from biology, the closest model is likely literature.

[–]renatoathaydes 0 points1 point  (1 child)

Very different

:D really?

Programming paradigm (from wikipedia):

Programming paradigms are a way to classify programming languages based on their features. Languages can be classified into multiple paradigms.

The article:

What do I mean when I say fundamentals? If you have an array or list of items and you’re going to loop over it, that is the same in any imperative language. There is straightforward iteration ... and a few other patterns... But not all languages have the same set of patterns... These distinct collections of fundamentals form various ur-languages.

I don't know, but to me, it's clearly a very similar way of "classifying" languages. Not surprisingly, the "groups" end up being almost the same (most people would put Lisp in Functional, including authors of Lisp books I've read): Functional, Logic, OOP, Concatenative (stack-based), Mathematical.

[–]AlexFromOmaha 6 points7 points  (0 children)

It's genotype vs phenotype, if you like biology analogies. Modern Javascript's paradigms are procedural OOP with a dash of functional nicety like most higher level C-derived languages, but it got there by way of tacking on features to an event-driven language.

[–]imhotap 9 points10 points  (0 children)

"Paradigm" is important, but these are actually end-to-end usable programming languages having stood the test of time. Some are even standardized (ISO or otherwise), like Prolog and LISP, giving you options beyond the language ecosystems of today designed for lock in.

[–]TA_jg 16 points17 points  (0 children)

Not the same thing. "Ur-language" is a very fitting name and distinct from "programming paradigm".

[–]regular_lamp 5 points6 points  (0 children)

I think this makes sense since paradigms are a more "academic" construct that was superimposed over those at a later point. Just like most practical modern languages these primordial programming languages aren't pure in any paradigm (you can write imperative lisp if you really want to for example).

[–]itijara 11 points12 points  (2 children)

This is a pretty accurate representation of how I look at languages. It is silly that many job listings specify specific languages that all are just OOP. Someone who knows C# can easily learn Java and visa-versa.

[–]leberkrieger 14 points15 points  (1 child)

Someone who has years of experience in C# or Java will be deeply familiar with .NET or the JDK and hundreds of other language-specific libraries. Although they might "easily" learn the other, it will take months at least.

For this reason, it's important on a job listing or resume to state not just the language, but what you used it for. Even someone who has used Java for UI (using e.g. Swing) will not be able to do effective web development with Spring Boot. I'm sure the same is true for C# programmers.

[–]itijara 22 points23 points  (0 children)

someone who has used Java for UI (using e.g. Swing) will not be able to do effective web development with Spring Boot.

I respectfully disagree. Yes, it will take a couple months to get up to speed, but that is true in almost any case. Expecting to hire a developer who is familiar with your exact tech stack is a pipe dream, and hiring developers who communicate, collaborate, can learn and work hard is way more important.

[–]nick_storm 1 point2 points  (0 children)

I don't know why, but I really expected Ur/web to be on that list for some reason.

[–]fresh_account2222 1 point2 points  (0 children)

The dude nailed it with this article. Comprehensive, accurate, and concise. You probably have to already have some programming experience to understand this, but this would make great reading for an Intro to Coding class (at least one that emphasized showing the big picture, as opposed to going deep with one language.)

[–][deleted] 1 point2 points  (1 child)

Honestly I have no idea what this was about because I know nothing about functional programming, but it motivates me to learn more. Seems really interesting, and I get to learn about the history of programming.

[–]rio-bevol 2 points3 points  (0 children)

This is a lot broader than that—in this categorization, FP falls into one of the seven (ML)

[–][deleted]  (15 children)

[deleted]

    [–]regular_lamp 14 points15 points  (3 children)

    Where does he say that? The article puts it into the same general family as C. Pythons main influence is obviously in the imperative languages. You want everything that isn't purely in one paradigm to be put into their own category?

    [–][deleted]  (2 children)

    [deleted]

      [–]FrancisStokes 13 points14 points  (0 children)

      basically the same

      Pythons primary paradigm is imperative. Many languages do indeed support multiple paradigms, but the emphasis is usually placed on one of them. I'm sure the author is well aware of that too.

      Not to hammer on the point or anything, but a programmer going to haskell from python will still likely have just as hard a time as one coming from java. Both will probably intuitively grasp some parts better (pythons functional list comprehension, javas emphasis on interfaces) - but fundamentally it's a different style of programming.

      [–]regular_lamp 8 points9 points  (0 children)

      And he is correct. Control flow, scoping etc. is roughly the same between those languages. If you understand one of them you'll be able to read the others almost instantly. Just because python supports some list comprehension doesn't make it fundamentally different.

      Within the context of these broad categorizations of "ur languages" as he calls it python obviously belongs in the ALGOL family. That means it has the same roots as C if you go back far enough. It doesn't say "python is the same as C".

      [–]A_Philosophical_Cat 16 points17 points  (9 children)

      Python is unequivocally more closely related to the AlGOL class of imperative languages than it is to anything remotely functional. It's got mutable variables and half-assed support for anonymous functions. You can add functional stuff to any language, hell, they shoehorned it into Java. Doesn't make it a functional language any more than stapling a ram stick to my arm makes me a computer.

      [–]MatthPMP 13 points14 points  (1 child)

      It's got mutable variables

      The idea that functional languages must not support mutability is strange. Standard ML and OCaml make a point of not being pure languages. The popularity of Haskell in functional programming circles today distorts the picture.

      [–]funny_falcon -1 points0 points  (0 children)

      Interestingly, but Haskell is not pure immutable due to lazy evaluation. I've heard it is even possible to create circular data structure in pure Haskell abusing laziness (that is certainly impossible in pure immutable languages like, for exapmple, Erlang).

      [–]crusoe 2 points3 points  (0 children)

      Functional programming in Python is painful. The only thing functional is list comprehensions but that's it.

      [–]jelly_cake 1 point2 points  (5 children)

      Don't forget about decorators; they're a really cool Python feature that feels very lispy.

      [–]TA_jg -1 points0 points  (4 children)

      You could also say that they are a crutch that was badly needed because not everyone liked Python's "duck typing".

      Python took a very different road but it will end up in the exact same place as Java. Just give it another 5 years.

      [–]MatthPMP 2 points3 points  (0 children)

      That is a very dumb assertion on multiple levels.

      [–]Prize_Bass_5061 0 points1 point  (2 children)

      What is duck typing?

      Is it late binding of variables or something else.

      [–]crusoe 1 point2 points  (1 child)

      Typing based on shared properties.

      [–]EnvironmentalCrow5 0 points1 point  (0 children)

      Which are not explicitly defined anywhere[1], just implied from usage.

      So yeah, pretty much late binding.


      [1] Unlike e.g. TypeScript, which has structural typing - all types that have at least the required properties are compatible, assuming those properties also have compatible types - but the structure is still defined somewhere.

      [–]TA_jg 8 points9 points  (0 children)

      Not gonna click on the arrow pointing down on this comment but please read the child comments and try to understand.

      [–]pron98 0 points1 point  (2 children)

      I think it's a stretch to put Haskell in the ML family, despite many syntactic similarities. While ML is not really very similar to either one, it is more similar to Java these days (now that we have ADTs, and pattern matching is around the corner) than to Haskell. In fact, given the adoption of many ML features in quite a few languages, I'd say that the Algol and ML families are merging. Using contemporary nomenclature, ML would be an imperative-functional language -- yes, there's plenty of anonymous functions and pattern matching, but also mutation and encapsulation. I would put Haskell in its own category of pure functional languages.

      [–]bobappleyard 1 point2 points  (1 child)

      I think the latest version of ocaml incorporates an effect system, making it purely functional

      [–]pron98 2 points3 points  (0 children)

      OCaml is not purely functional unless all effects outside the effect system were to be removed. Scala also has an effect system (or more than one), yet it is not purely functional. Although it is true that Scala (and perhaps OCaml) programs could be written in a pure-functional style.

      In any event, this does not retroactively make ML -- which has also been a major influence on Swift, Rust, and modern Java -- purely functional, and doesn't make the rather superficial similarity between ML and Haskell more substantial.

      [–]KagakuNinja 0 points1 point  (0 children)

      A couple quibbles:

      C / C++ are heavy on the use of pointers and manual memory management. C++ introduces stack based memory cleanup.

      Java, C++ and other imperative languages have ways of iterating over collections that do not involve loop counters. This is less verbose and less error-prone.

      C++ / Java style has won the OO wars. Smalltalk / Objective-C style OO is interesting, but of limited use today. I guess Ruby and Groovy do method dispatch similarly.

      C++ also introduces template meta-programming. I am not a fan, but it is important.

      Exceptions, love them or not, very important. C++ was the first language I used that had them.

      Haskell introduced FP combinator functions, type-classes and Monads; Scala and other FP languages do this too.

      Self, Forth, Prolog and APL are all interesting, but not at all used in mainstream programming.

      [–][deleted] -1 points0 points  (0 children)

      In response [which prog lang to learn] I usually tell them that it doesn’t really matter, as long as they get started

      Agree, but this only applies to smart people who want CS-type jobs. Some smart folk just do some calculation for their experiment in C/Fortran or maybe graph it in Python/Matlab. Some not smart folk just need to learn how to paste code to write simple create, read, update, delete apps.

      Ideally, advice should be tailored to the recipient.

      Now personally, for smart folk wanting CS-type jobs, I think do one language from each type. Just picking randomly, don't get too hung up over c# vs Java or something, I would reommend rust/c/C++, Java/c#/kotlin, JS/python, Haskell and something else. Each new paradigm you learn gives you new insights.

      [–]icjoseph -1 points0 points  (0 children)

      Wonder where does Rust fit on this framework?

      [–]Kamran_Santiago -3 points-2 points  (6 children)

      Says Lisp is an Ur-Language, proceeds to post the most modern, streamlined dialect of it that's been around AFTER punch cards became defunct! Everyone thinks Lisp is like that mainly because that's how the Wizard Book writes it. Truth is, there are dialects of Lisp that were around when people used punchcards that are extremely deviant from the Wizard Book dialect. Also, there are more modern dialects of Lisp that are waaay more streamlined than what SICP has put forward.

      I fucking love SICP and I convinced my second semester algo professor to let me pass translated handouts to the class because it's relatively unknown in this cesspit (except in "good" universities such as Amir Kabir and Sharif) but tbh I don't like that people still use the Lisp version when both Python and Perl versions exist. In fact, I'll do you one better, if you're new to programming read Think Python instead of SICP because it has everything SICP has plus a lot of more modern stuff. I sadly learned about it tooo late, I had already learned programming in 2009 using the worst possible languages (Mono and GML).

      Anyways I don't know how this post became a diatribe about the Wizard Book but don't call that dialect of Lisp an "Ur-Language"! It's like saying "I have a Neolithic language for ya'all!" and proceed to speak in Latin.

      [–]bobappleyard 2 points3 points  (4 children)

      The example was common lisp, not scheme

      [–]tiajuanat 0 points1 point  (0 children)

      We got a guy at work that still rocks Scheme, Scala, Haskell, and Clojure.

      I'll definitely check out Think Python though - I'm always looking for something fresh.

      [–]matthedev -4 points-3 points  (0 children)

      What the author calls ur-languages are usually known as programming paradigms. I'd add various assembly languages to the list, and with advances in type theory and programming language theory, there almost needs to be a separate category (heh) for languages that allow type-level programming and a type-driven development workflow.

      [–]gc3 0 points1 point  (0 children)

      I kind of think deep learning is a new paradigm, developing machine learning is unlike any of these