News for hackers. Stuff that matters.
Re:Things I Was Wrong About: Types by adnzzzzZ on Sunday September 27, 2020 @05:11AM (#24605290)
I don't really see most of my code being improved that much by types and I also see a lot of extra complexity that people in the sphere I am (indie games) have to deal with when using typed languages. It just doesn't seem worth it. When you have to spend a lot of time fighting your language, and handling numerous extra concepts that don't exist in an untyped language because they don't need to, it feels like the people who swear by typed languages that they simply like creating extra work for themselves as a way to avoid doing what's actually needed to be done, just because they want to feel productive.

I also suspect that a lot of this has to do with people's personalities around the concept of borders. Some people like well defined borders in general in everything they do because they approach life from a more procedural perspective, and for procedures to work they need things to be in the right boxes and in the right places. While others prefer borders to be undefined and more free-flowing because more information can pass through concepts and that allows for a more unstructured design process. It only puzzles me that there's so much energy in indie game development for highly bordered programming environments (i.e. all the energy being put into gamedev Rust libraries) when indie developers tend to be people who value borders less, as do all creative types. But I guess people really like types...

Re:Things I Was Wrong About: Types by loup-vaillant on Sunday September 27, 2020 @05:34AM (#24605400)
Statically typed languages (or at least the good ones) are disciplined so the programmer doesn't have to.

If you can work reliably with dynamic typing, that means you are very disciplined about giving the right data to the right function, in exactly the right form. That you are very disciplined about tests, possibly including fairly stupid-looking unit tests (which aren't actually stupid, at least in a dynamic context). Adding static typing on top of that wouldn't help much of course.

When I write something from scratch however, I found that static typing actually speeds up my development. It's less work, not more. Because I don't have to write as many tests, or even worry about huge classes of errors — the compiler (and if I'm lucky, my editor/IDE) just checks them for me.

I don't know the work you do, but I bet that your style could benefit from some static checks. Perhaps not the mainstream ones, but your scripts work somehow, don't they? That mean they respect a number of invariants, some of which could certainly be checked at compile time, saving you significant time on stupid bugs. The result won't be TypeScript or Rust, but I don't think it would be fully dynamically typed either.

Re:Things I Was Wrong About: Types by williamdclt on Sunday September 27, 2020 @09:36AM (#24606516)
> I found that static typing actually speeds up my development. It's less work, not more.

It's a point that comes back often, and that I totally agree with so it's worth reiterating. In addition to the improved dev tooling (autocompletion, hinting, refactoring), being able to write large swathes of code without actually running it and being 100% confident that it's all _valid_ (not bug-free of course) just takes a huge load off my mind.

Of course, there's huge differences between languages like Java and languages like Typescript. Talking about "typed languages" as a homogenous concept often doesn't make a lot of sense

Re:Things I Was Wrong About: Types by pansa2 on Sunday September 27, 2020 @11:19AM (#24607292)
> being able to write large swathes of code without actually running it and being 100% confident that it's all _valid_ (not bug-free of course) just takes a huge load off my mind.

I've heard similar things before, e.g. "static typing allows you to find bugs in your code without even running it".

Perhaps the reason I'm a fan of dynamically-typed languages is that I don't see the benefit of this. Maybe my workflow is unusual, but I don't write code without running it - I run tests every time I add a few lines.

Re:Things I Was Wrong About: Types by loup-vaillant on Sunday September 27, 2020 @11:57AM (#24607592)
OCaml has a REPL. I use it all the time to check that a new function I just wrote is correct. Yet I still get huge benefits from the static typing: many of my errors are stupid type errors, and having the type checker tell me about them, rather than a runtime error (or worse, a wrong result), makes early prototyping much faster.

Even if I already have a REPL. I believe the main reason is because the type checker is much closer to the source of my errors than runtime checks or tests are.

Re:Things I Was Wrong About: Types by nonbirithm on Sunday September 27, 2020 @03:54PM (#24609643)
When moving from a dynamically typed language to a statically typed one, about the only thing I end up missing is hot reloading.

In gamedev, static types don't help when you have a constant value you have to change that tweaks the gameplay buried inside a compiled class that you want to balance out. Changing that one constant means either putting it in a script, which is usually written in a dynamically typed language, or recompiling the whole program, testing, changing the value, and repeating.

The only real reason I choose dynamic languages is because I spent hours on that last cycle just recompiling the whole program and throwing away all the state for a single small change, then getting the engine back to the previous state I was debugging in. I still don't understand if it was a bad habit or just how my mind wants me to program. I expect to be able to interact with my program and see how changing things affects the behavior very quickly, and a compile cycled shuts down that mode of thinking entirely. I remember Steve Yegge's essay that mentioned this, that "rebooting is dying." [1]

There were a lot of times I could write scripts, but the fact was that most of the time the code I wanted to tweak slightly was compiled, and that required a full module recompile every time. The fact is that if some of my code can be compiled, then I will probably end up changing the compiled code at some point, and that means a lot of waiting.

If C# had the ability to hot reload a class like a dynamic language to cut down the recompile cycle, I would be happy, but it sounds like it isn't possible. The old code will be mixed with the new code leading to instability.

So I've been spoiled by a dynamic language (Lua) while acknowledging I made a trade-off for one single feature. In my case if I used a statically typed language I would lose out on certain things and gain others, but dynamic program rewriting seems to best coincide with how I think, and I'm not sure how if I should change that.

[1] http://steve-yegge.blogspot.com/2007/01/pinocchio-problem.ht...

Re:Things I Was Wrong About: Types by loup-vaillant on Sunday September 27, 2020 @06:48PM (#24610810)
Hot code reloading and static typing are not incompatible.

On a trivial level, C and C++ can unload & reload DLLs at runtime. On a less trivial level, I believe the Yi editor, written in Haskell, can do hot code reloading. On a practical level, I use the XMonad window manager, whose configuration involves modifying a Haskell source file (the main one, actually), and hitting some shortcut. If my modifications are correct, the whole things reloads without loosing any state (my windows are still at the same places).

Re:Things I Was Wrong About: Types by adnzzzzZ on Sunday September 27, 2020 @11:32AM (#24607378)
I think the same. This is especially true for games where you're absolutely running the game again for everything you change, and in case anything is wrong it's generally very obvious visually.
Re:Things I Was Wrong About: Types by orwin on Sunday September 27, 2020 @06:30AM (#24605639)
Yes. Try prototyping for a quick POC/casual demo with javascript, then try with typescript. If you get back to your demo two month later (or have one other person to explain your code to), typescript is Infinitely superior.

For quick hacks types are not useful though.

Re:Things I Was Wrong About: Types by i6ruce on Sunday September 27, 2020 @09:34AM (#24606495)
Unless you're quite experienced with them and use as a thinking tool and not as burden.
Re:Things I Was Wrong About: Types by TeMPOraL on Sunday September 27, 2020 @06:48AM (#24605701)
I can second the experience. I write a lot of Common Lisp, and these days it's typed Common Lisp for me. It adds very little overhead in terms of code writing speed, but continuously stops me from making stupid mistakes (like e.g. forgetting a function I'm calling returns a sequence and treating it as a scalar value). My comfort of writing is much better, because I spend less time in interactive debugger hunting my own typos.
Re:Things I Was Wrong About: Types by asiachick on Sunday September 27, 2020 @08:08AM (#24606021)
how many times have you not used bash/dos/pwsh scripts because it's not typed?

Maybe there's a place for both?

Re:Things I Was Wrong About: Types by loup-vaillant on Sunday September 27, 2020 @11:16AM (#24607254)
I can say what I do use Bash for: create files & directories, and simple string replacements in files. Anything more involved goes into a proper program. Usually OCaml, though I can fall back to more mainstream languages (Python, C) if I need a wide audience to be able to read it, and the program is simple enough that types aren't really a problem to begin with.
Re:Things I Was Wrong About: Types by Aeolun on Sunday September 27, 2020 @08:29AM (#24606145)
Javascript is for scripts that fit in one file. Anything else is typescripy.
Re:Things I Was Wrong About: Types by samhain on Sunday September 27, 2020 @05:33AM (#24605390)
Aren't you falling into the same trap that the post explains? That there are nuances around when types are useful and not useful? An indie game developer might spend a lot of time designing methods of gameplay and artwork for the game, but that doesn't mean that types should go out the window for all levels of programming.

Wouldn't it be better to approach this by which problem we are trying to solve? A script that is run during development, where resources are unconstrained, and stability is not an issue, should absolutely value the time it takes to develop and maintain the script. So using a typed language may not be useful here. A situation where small optimizations make large improvements might benefit from a typed language, maybe a physics engine of a game intended for multiple platforms?

In the OP, the author approaches it from a "systems" perspective, that when you need either of the 3 scenarios, then you might consider using types. Type inference, Sum/tagged union types, and Soundness, which I think could easily apply to certain areas of game development. Ignoring the nuance around the issue, and being dogmatic that all scenarios in a given field do not need types is ignoring that what we're really doing is writing in languages that need to be interpreted by both humans and machines.

Re:Things I Was Wrong About: Types by darkerside on Sunday September 27, 2020 @09:09AM (#24606359)
This seems likely. It took me embarrassingly long to realize the fact that you can't understand the benefit of a feature you don't understand. Seems like an obvious tautology, but it's one I fell for over and over, and one I think grandparent is guilty of here.
Re:Things I Was Wrong About: Types by sammorrowdrums on Sunday September 27, 2020 @05:41AM (#24605433)
I think it depends on size or codebase, how many people are working on things and how long you can afford to develop before releasing.

I do mostly work with python and JS, but last Christmas I learned Rust, and it strongly occurred to me that exhaustive matching, no nulls, borrow checking and strong type inference would be a real boost to development given the initial time to build the codebase up. I'd put money on them removing hours of hunting subtle bugs, and on missing the ramifications of refactors.

I built some small scale game stuff using SDL2 for Advent of Code and I enjoyed rust for doing that a lot.

I think also dynamic languages work best when developers actually are knowledgeable about the underlying types and effectively write code in a typed manner anyway. It's a much worse trade-off when function signatures actually avail of loose typing to do strange things.

Re:Things I Was Wrong About: Types by awild on Sunday September 27, 2020 @05:27AM (#24605367)
What languages have you worked with? As per the OP, there are certain languages where types are much more expressive and add something to the programming experience.

Learning haskell changed a lot about the way I think about programs and that is even as someone who primarily writes in java.

Re:Things I Was Wrong About: Types by sideshowb on Sunday September 27, 2020 @05:24AM (#24605354)
Maybe it's a case of problem complexity. I think of types as a tool to help cope with certain things. If you're building a garden wall you probably don't need CAD. For a 747, you probably do. Though aircraft predate CAD so it's clearly not impossible to do without.

I dislike types in 30 lines of python because they're unnecessary complexity. I like them in 10000 lines of c++ because they do some of the thinking on my behalf.

Re:Things I Was Wrong About: Types by i6ruce on Sunday September 27, 2020 @09:39AM (#24606533)
> I dislike types in 30 lines of python They are already there you just don't want to acknowledge them. You can build the same prototype in strictly typed language just by sticking to some primitive types like int/string and type inference, and the progress toward something more complex as your prototype grows. I personally prefer to use types right away, so type system can guide me further and show me when I'm assuming something in a wrong way.
Re:Things I Was Wrong About: Types by jondubois on Sunday September 27, 2020 @06:15AM (#24605573)
I agree. I think the downside of static typing is that it encourages developers to pass around complex types between functions instead of simple types and I think this is a mistake.

If you have the option between creating a function which accepts a string (e.g. ID) as argument or accepts an instance of type SomeType, it's better to pass a string because simple types such as strings are pass-by-value so it protects your code from unpredictable mutations (which is probably the single biggest, hardest to identify and hardest to fix problem in software development). I think OOP gets a lot of blame for this and it's why a lot of people have been promoting functional programming but this blame is misguided; the problem is complex function interfaces which encourage pass-by-reference and then hide mutations which occur inside the blackbox, not mutations themselves. Mutations within a whitebox (e.g. a for-loop) are perfectly fine since they're easy to spot and happen in a single central place.

If you adopt a philosophy of passing the simplest types possible, then you will not run into these kinds of mutation problems which are the biggest source of pain for software developers. Also you will not run into argument type mismatch issues because you will be dealing with a very small range of possible types.

Note that this problem of trying to pass simple types requires an architectural solution and well thought-out state management within components; it cannot be solved through more advanced tooling. More advanced tooling (and types) just let you get away with making spaghetti code more manageable; but if what you have is spaghetti code then problems will rear their ugly heads again sooner or later.

For example, a lot of developers in the React community already kind of figured this out when they started cloning objects passed to and returned from any function call; returning copies of some plain objects instead of instances by-reference provided protection from such unexpected mutations. I'm sure that's why a lot of people in the React community are still kind of resistant to TypeScript; they've already figured out what the real culpit is. Some of them may have switched to TS out of peer pressure, but I'm sure many have had doubts and their intuition was right.

Re:Things I Was Wrong About: Types by willtim on Sunday September 27, 2020 @09:36AM (#24606515)
If you use String for all your data types than you are no better than a dynamic language. There are many string like things that benefit from their own types, e.g. currency, identifiers, post codes. Such types should only be created from a parse of valid strings, i.e. no empty strings, whitespace, illegal values etc. They do not have to be Alan Kay "objects", despite what your language or thought leadership is telling you. They should be values with value-based equality. A modern statically typed language should let you define such a type in a few lines. This is all done in order to make illegal states unrepresentable, which is what type systems are for.
Re:Things I Was Wrong About: Types by Jtsummers on Sunday September 27, 2020 @02:10PM (#24608756)
> If you use String for all your data types than you are no better than a dynamic language.

I once read a Haskell (I believe, may have been SML or OCaml, this was a while ago) tutorial (can't find it anymore) that did this. It was infuriating as it completely hid the benefit of the type system. Essentially, details fuzzy, it was creating a calculator program. Imagine parsing is already done and had something like this:

  eval "add" a b = a + b
  eval "sub" a b = a - b
  ...
Where the parsing should've at least turned those strings into something like an Operation type.

Sadly, I've seen similar programs in the wild at work (not using these languages, but with C++, Java, C#) where information is encoded in integers and strings that would be much better encoded in Enums, classes, or other meaningful typed forms.

Re:Things I Was Wrong About: Types by willtim on Monday September 28, 2020 @03:33AM (#24613969)
Yes, every statically-typed language has a dynamic language as a subset. It is up to the author to use and apply types. One can certainly write Haskell where everything is in IO and everything uses Strings.
Re:Things I Was Wrong About: Types by marcosdumay on Sunday September 27, 2020 @09:24AM (#24606429)
You seem to have experience only on languages where strings are immutable, and objects are always mutable. Those properties are not universal.

And yet, despite correctly assessing the problem, you insist on fighting objects instead of mutability.

Re:Things I Was Wrong About: Types by andrekandre on Sunday September 27, 2020 @05:57PM (#24610449)
one of the interesting things in cocoa/foundation is the types are all objects, but they make a big distiction between NSArray and NSMutableArray, same with strings, dictionaries and many other objects

to make things mutable you have to clone them as such and i cant really think of a single api in cocoa/foundation that vends a mutable array or string...

i think its a very good point...

Re:Things I Was Wrong About: Types by alkonaut on Sunday September 27, 2020 @07:38AM (#24605882)
The correct thing is imho to pass an immutable SomeType or an interface that only exposes the parts of SomeType necessary for the calculation and doesn’t allow mutation of the object.

Of course you don’t send around references to mutable objects and of course you only send to a function just what it needs - but that’s regardless of type system.

Re:Things I Was Wrong About: Types by jondubois on Sunday September 27, 2020 @08:10AM (#24606042)
Sometimes this will be the best approach possible but adhering with this principle too strongly can overcomplicate the general design/architecture - It can give developers a green light to start passing around complex types all over the place and harms the separation of concerns principle.

In terms of modularity and testability, the ideal architecture is when components communicate with each other in the simplest language (interface) possible. Otherwise you become too reliant on mocks during testing (which add brittleness and require more frequent test updates). I think very often, static typing can cause developers to become distracted from what is truly important; architecture and design philosophy. I think this is the core idea that Alan Kay (one of the inventors of OOP) has been trying to get across.

'I'm sorry that I long ago coined the term "objects" for this topic because it gets many people to focus on the lesser idea. The big idea is "messaging"' - Alan Kay

It's very clear from Alan Kay's writings that when he was talking about 'messaging' he was talking about communication between components and he did not intend for objects to be used in the place of messages.

Re:Things I Was Wrong About: Types by loup-vaillant on Sunday September 27, 2020 @11:26AM (#24607329)
Abandoning a feature just because it enables a misuse is the wrong way to do it in my opinion. Yes, some inexperienced, stubborn, stupid, or hurried developers will pass around complex types when they really shouldn't. But no, this drawback does not nullify the massive advantages of (good) static typing.

Sure, interfaces should be kept small. Let's to just that, then! Recognise that we want our classes/functions/modules to be deep (small interface/implementation ratio), and frown upon shallow instances in code reviews.

No need to give up static typing.

Re:Things I Was Wrong About: Types by andrekandre on Sunday September 27, 2020 @06:15PM (#24610575)
i think messaging is orthogonal to strong or weak typing (hence small/strongtalk, objc, self etc dont let you automatically coerce objects to different types than you expected) and those systems all use messaging
Re:Things I Was Wrong About: Types by nicoburns on Sunday September 27, 2020 @06:46AM (#24605696)
In many langauges it is possible to have complex types that are pass-by-value. Rust also completely solves the mutation issues with pass-by-reference by putting the mutability of references in the function signatures and only allowing one mutable reference at a time.
Re:Things I Was Wrong About: Types by jondubois on Sunday September 27, 2020 @06:55AM (#24605724)
But still, I think it does not fully solve the architectural issue or encourage good architecture (though it can certainly help reduce bugs)... In this case you may end up with lots of duplicate instances in different blackboxes which may not be a good thing either.

The point of good state management is to ensure that each instance has a single home. As soon as you start passing instances between functions/modules/components, you're leaking abstractions between different components. Sometimes it is appropriate to do this, but most of the time it's dangerous. Components should aim to communicate as little information about their internal state to other components as possible.

Re:Things I Was Wrong About: Types by viraptor on Sunday September 27, 2020 @08:57AM (#24606293)
It really depends on the language. Some still help you use this case in an amazing way. For example rust will allow you to create an enum which can be a FooId(&str). (Or add extra 4 lines to get an owned String that's immutable)

Now you've got an immutable id string, you can access as easily as the bare one, but now you can't mix it with other types of IDs, so you won't pass it to something expecting BarId by accident. As a result - no black boxes and a clearer design.

A variant of this is the cause of many Linux kernel issues. They basically had to cram it into macros to prevent passing real/kernel pointers to userspace by accident, because pointer is a pointer is a pointer.

Re:Things I Was Wrong About: Types by valuearb on Sunday September 27, 2020 @11:45AM (#24607486)
In Swift Structs are immutable and passed by value, class objects are mutable and passed by reference.

Using a struct is infinitely preferable to a string.