Some older PS1 games didn't work with the Dual Shock in analogue mode. You needed to press the button to disable the analogue sticks to play those games.
Over the last 3 or 4 decades, our procedural and OO languages have slowly been absorbing the best ideas from "FP languages." We're getting to the stage where the very idea of a "functional language" is eroding.
Sure. I don't mean to say that imperative programming is going anywhere.
If you're looking for programming languages with no support for imperative programming, Excel is pretty much it. Even Haskell has robust support for sequencing actions. If it didn't, I don't think we'd be talking about it at all.
What I predict is that ideas from FP will continue to bubble up into the mainstream. Like prior inventions, they won't be presented as a thing that asks you to rework all of your algorithmic code. They will instead be polished and presented in a way that makes them work more as extensions to what you can already do.
If you squint a little bit, Haskell's do-notation is already available in mainstream languages in the form of async/await syntax. async/await is not quite as general as the original Haskell solution, but it also doesn't ask you to completely rethink the way you design algorithms.
Lambdas are now a requirement for any modern programming language. Monadic promises are how asynchronous programming is done. Rust is basically OCaml except with typeclasses and without a GC.
Inch by inch, ideas from FP bubble up into mainstream programming.
I predict that algebraic effects (a la Koka) are next, but it'll be a while before the industry is ready for it.
Further, these extra components are easy to omit if you don't want to use them.
The REPL that we offer in the distribution doesn't include any of the analysis logic and it's just 1.7mb once compiled (on my M1 Macbook). I'm not sure how much smaller it gets if you omit CodeGen.
Luau already has some notion of nominal types to deal with the fact that the Roblox API is basically a ton of C++ classes that have been mapped over via the FFI. Some of these types are totally structurally identical and yet incompatible.
We'd like to afford the same kind of ideas for native Luau code, but we're not there yet.
There is a transpiler in the source tree, but I expect it needs a polish pass. We haven't put it to use in quite some time.
In particular, I am pretty sure that it won't do the right thing when it encounters the extra syntax we've added to Luau. So far, that's an if-else expression and a continue keyword. Transpiling those accurately will take a bit of work.
I did a little bit of GBA homebrew development back in its heyday. It is a really fun little bit of hardware to hack on.
It's powerful enough that you can write your whole game in C++, but not so powerful that you should rely on the system allocator for anything.
It's in a lovely sweet spot for a particular dialect of zero-overhead C++ that's really fun to write.
As a simple example, I had a little class library of data types that were crafted to exactly map to the hardware registers of the GBA. The whole thing inlined away to nothing.
The right balance here can depend on the specific business you're working in.
Some companies earn the privilege of a super tenured core team of engineers who work on their product for an extended period of time. They will choose different tradeoffs from a team that needs to adapt to higher turnover.
I understand what you're saying, but something I have noticed over the years is that the amount of code that I can make sense of at any given time is actually proportional to what I can see onscreen at any given moment.
I have had pretty good luck cheating this in a bunch of ways: I use a small font, a big display, and I use a terse programming style.
Once you internalize a bunch of common higher-order functions, you learn how to draw a ton of meaning out of a relatively small number of terms.
I switched to the Dvorak keyboard layout sometime in the early 00s.
I've never owned a keyboard that was actually physically labelled for Dvorak, so I _cannot_ type if I can see my fingers. The lies printed on the keycaps throw me off every time. :)
Most modern C++ code that I've seen restricts code to declaring a single variable per statement.
It's not really a big deal because things are also always introduced at the latest possible position. Each is also typically given an initializer. I'd consider it suspicious if I were to see C++ that declared 3 uninitialized pointers back to back like this.
And then you get to the codebases where the authors have chosen to embrace auto and type inference... :)
Hello! I am the lead developer of the Luau type checker.
I actually hadn't heard of Teal! I don't think it existed when we started.
Judging from the Teal documentation, I'd venture that it looks pretty similar to Luau in everyday use.
If I were to guess, I'd venture that the biggest differences are probably the kind of type inference we do (Luau's inference engine draws inspiration in equal parts from OCaml and TypeScript), a bunch of Roblox-specific features, and that our inference engine is all C++ for performance.
I don't think many people would enjoy that at all.
The appeal of games like Dark Souls (and Slay the Spire!) at high difficulties arises from the knowledge that you _will_ win if you are clever and observant enough.
It's the learning process that keeps players coming back to these games, not the Game Over screen.
I did a bunch of professional Haskell work in a prior life[1]. Most of its 'secret weapon' status springs from the way Haskell lets you control side effects.
We had a fantastic unit testing harness[2]. With effect tracking, you can arrange for your harness to put precise fences around nondeterministic code. You don't need to rely on experience and discipline to ensure that tests are reliable or fast. The type system does it for you.
Effect tracking also makes concurrent code easier to write. You have a great deal of control over how and when threads can be created, and what kinds of logic is permitted on those threads.
GHC's IO manager offers green threads and async IO, so rather than a select loop, you just fork threads and perform "blocking" IO calls. You get about the same efficiency as a select loop this way.
Lastly, something we learned to appreciate over the years is that Haskell is easier to refactor. When you combine the rigid type system, effect tracking system, and ease of writing unit tests, it becomes very easy to refactor old Haskell. It doesn't really matter how bad the old code was or whether the original author is around to help you at all.
If you intend for your product to evolve continuously forever, this is truly a secret weapon.
If you are going to expect me to run your software in an always-on manner, I would greatly appreciate a native application.
I frequently do light computing on a Surface Go. It's a delightful little device and I love it, but it is not powerful enough that I can leave gmail, Slack, and Discord open all the time.
I don't have enough RAM to run another web application but I could very easily afford a native app or two.