IF Authoring, Array Programming, and Fourth-Generation Programming

If any programmers among us (and that includes many IF authors!) could take the time to answer one or more of the following questions, you would be helping me with a project I am working on:

  1. Which methods, functions, or other features you associate with IF-authoring languages do you miss most when programming in languages that are not IF-focused?
  2. Which methods, functions, or other features you associate with array programming languages (e.g. J) do you miss most when programming in other languages?
  3. Which methods, functions, or other features you associate with fourth-generation programming languages do you miss most when programming in languages from previous generations?

I am looking forward to your responses!

I haven’t run into the idea of array programming languages, and “4GL” is a fossil concept that database designers talked about when I was a kid. Turns out they were confusing the idea of “API” with “programming language”.

I think of the programming language generations as (1st) C; (2nd) C plus types and memory management: C++ and ObjC; (3rd) runtime interpreters: Java/Perl/Python/JS/C#; (4th) the second generation strikes back with much better type inference: Swift/Go/Rust. Functional programming isn’t a generation because it’s been stumbling around in the background all this time. Yes, there were languages before C but I don’t need numbers for them because I’m not that old. None of this particularly maps to the “generatiions” that were up in the air in the 70s and 80s.

I do think Inform 7 embodies a genuinely new and interesting approach, but it’s not quite solidified. I don’t know what it needs to become truly usable as a general and scalable programming model. If I did, I’d be rich and famous, or at least securely employed.

4 Likes

I sometimes miss the ability to have structs in Inform 6/7. Just occasionally they would really simplify some code.

I’ve started using algebraic (sum) types in Rust, and really like them. I’m not aware of any IF languages that support them.

2 Likes

4GL - That makes me giggle. :grinning:

The bold future was supposed to be that you’d write 4GL and the tools would translate into efficient machine code and we wouldn’t need “real” programmers any longer. It was as much a pipe dream as “AI” replacing developers today.

@Dannii - Rust is a truly awesome language. I love it. Algebraic types are fairly common in functional languages like Haskell. For me, developing in Rust has been such a breath of fresh air, allowing me to finally dump a lot of the design garbage I had to deal with in OO languages.

2 Likes

Thank you for sharing your thoughts! This is one of those times when answers along the lines of, “There is a problem with the way the question is framed,” are quite helpful.

Are there any features of Swift, Go, or Rust that you miss while programming in other languages?

I would love to see a generalization on the Inform 7 approach. I hope you find a way!

Thank you for replying!

If that is what characterized 4GL, what characterized 5GL?

I guess the automation I was referring to is more accurately characterized as 5GL, not 4GL. I’ve not heard these terms in a long time, and I seriously question their utility in the modern development world.

The whole concept was flawed I think. What were classified as 3GL have often gone on to become more friendly and generally useful through large numbers of third party libraries and better tooling while still allowing fine-grained control of machine level details (although the exact level varies quite a bit by language). There are domain specific languages (4GL) for report writing, and database manipulation, etc. but they suffer from drawbacks - namely being linked to a particular technology and gluing them together into large complex applications puts you firmly back into the realm of the “obsolete” 3GL.

1 Like

Hey Mike, can you describe in simplified terms (for someone who only has a rudimentary knowledge of programming outside of TADS) what the design garbage of OO is, and how/why Rust deals with that? I’m in a phase of trying to really briefly “scope out” programming languages; at the moment I have a little grip on Python, and Java and JavaScript are pretty familiar because very similar in syntax to TADS.

1 Like

Well, a lot of this is just my opinion (opinionated developers are somewhat rare…not).

Object oriented development isn’t too bad, except when it comes to inheritance. Inheritance is ridiculously overused and is rarely (if ever) the best solution. Java, C#, and most other OO languages suffer from this.

Composition and developing to interfaces is almost always a superior solution.

2 Likes

The big wave of OO programming coincided with the beginning of the GUI era. I see a strong case for causality there.

People were trying to invent a manageable model for handling windows, dialog boxes, buttons, sliders, and so on. It seemed natural to say “okay, we have a Control class; that’s a base class for Button, Slider, and Menu; Button is a base class for RadioButton, Checkbox, and PushButton…” All the big UI toolkits went down this road.

I think this was in some sense a misfire. The inheritance model solves part of the GUI problem; you really do have a lot of methods (Click, KeyDown, layout handlers) which need to be type-dispatched to all these different classes. But GUIs also have a runtime structure which is not addressed by inheritance at all. A window contains a pane which contains a scrollable list which contains a bunch of buttons. This is a containment hierarchy, not a type hierarchy. Events like Click need to by dispatched by type and by containment!

The OO toolkits all deal with this by adding non-native dispatch chains for event handling. That is, they add a layer for passing events “uphill” which is outside the language’s OO model. (See, for example, the HTML DOM explanation of “event bubbling.”) And of course this is workable; UI toolkits are mature and usable.

But I don’t think anyone ever went back and said, look, if OO is supposed to be a universal problem-solving mechanism, how come it’s not enough for a GUI toolkit? Couldn’t we find a better mechanism that frosts the whole cake?

5 Likes

I’m going to fail this question, because I’ve never worked in those languages! I’ve looked over tutorials and written a couple of lines of code, but I have no real experience.

The features that I look forward to using someday are those better-founded type systems that I mentioned. Really solid generics (as opposed to C++'s janky templates). Sum (algebraic) types. Type systems that can express interesting features like “this function does not return” (the bottom type) or “this function can be called on a temporary reference without danger” (Rust’s borrowing semantics).

1 Like

I also think inheritance + virtual methods have a fundamental problem in that supposedly they should always uphold the LSP, but virtual methods allow changes in behavior that will always violate assumptions about the base class depending on exactly what your assumptions are. You can cover most cases, but any change is observable (and thus an LSP violation) if you approach it from a direction the original creator didn’t envision.

1 Like

Heh, pretty much everything you describe is in Rust. The never-returns type isn’t in stable Rust yet, but it has been in the Nightly builds for some time.

1 Like

Yeah, this is why I can refer to a “current language generation” without smirking. All three of those languages have similar ambitions. I don’t know which of them will win, but I’m confident that in ten years at least one of them will be a Common Big Gorilla in the industry.

2 Likes

One of the things I like about Rust is the whole zero-cost abstraction approach.

Especially static vs. dynamic dispatch is up to the developer, whereas it is more of a compiler optimization in Go and Swift. I only have a passing familiarity with those languages, so I am basing that on what I’ve read and may be incorrect.

1 Like

Java has some of the most egregious OO examples. For example SimpleBeanFactoryAwareAspectInstanceFactory, a factory for making factories. Luckily it’s “simple”!

Or apparently the longest class in Java: InternalFrameInternalFrameTitlePaneInternalFrameTitlePaneMaximizeButtonWindowNotFocusedState.

I think OO and inheritance still has its place, especially if you keep it to one or two subclasses max. Objects are useful abstractions for associating data and code. I don’t think Rust’s structs with trait implementations is greatly better, though Rust’s designers would have their reasons.

Functional programming has a lot of advantages too. Languages that let you mix and match are probably more useful on the whole. Some tasks will suit one paradigm and others will suit another.

2 Likes

On first glance, Rust traits look a lot like Java/C# interfaces, but they really are a different beast.

There will always be differences in how a developer values the features of one language over another. I acknowledge that and don’t want to contest anyone right there.

It seems to me that the essence of creating interactive fiction is to weave together technology with literature. And therefore there’s a need to access a previous body of work in the way that a playwright might reach back to up to Shakespeare or grab something from folk culture.

So, for me what’s important is not so much the semantics of a programming language but more the infrastructure of packaging, libraries, installers, plugins, etc. Can you serve over the web? Will it run on a Raspberry Pi? Can I integrate an NLP library, and so on.

3 Likes

Not having done any programming for the “real world”, I would have thought multiple inheritance was a great thing, given how useful it feels in TADS…

1 Like

Thank you, all who have responded.

In addition to some illuminating replies to my original post, I will be taking a reinvigorated interest in learning Rust away from this discussion.

1 Like