Moonside OP wrote
Reply to comment by neku in This is best programming comment of all time on Reddit by Moonside
Go lacks facilities for generic programming so you can't write in a sensible manner a function that operates on many different datatypes. This means you either need to write almost identical routines over and over or lose useful safety guarantees.
For example, consider a list containing strings ["lol", "lmao", "nada"]
(a value of type List String) and a list containing integers [1, 2, 3]
(a value of type List Integer). You wish to write two functions:
-
length
which returns the number of elements list contains. -
head
which returns the first element of a list.
If your language supports generic programming, you can just write functions length
and head
that work on lists containing any type of values. But since Go doesn't, if you want to have certain safety guarantees, you need to write a version of these functions for each type. In this case, you need to implement lengthString
, lengthInteger
, headString
and headInteger
. The comment author does this kind of a process by hand from a single "master" source code file to keep himself sane, but the way he uses those Canadian Aborigine Syllabics makes it look as if Go supported generic programming.
The loss of safety guarantees (if you don't wish to implement essentially same routines n times) comes from that you can mix elements of different types together in code which fails at run time and comes crashing down. In generic programming, you can guarantee that routine outputs a value of type t if the input value was a list of values of type t, or concisely, the routine's type is List t -> t
. (Your compiler can verify that your implementation abides by this rule, which is known as type safety in general.) As an another example, I can tell at a glance that a routine of type List t -> List t
may
- drop elements from the input list,
- repeat some elements of the input list and
- rearrange elements of the input list
but can't do anything else. But if the type was List Integer -> List Integer
I couldn't guarantee any of these properties. In fact a function I wrote, no matter what the parameter list is, could return the value [69]
and the compiler would still say nice. Go is even worse, since the other option is interpreting all values of being the most general one, Object (or something like that). You can't even know that it's a list of Integers anymore, it could be a weird mix and you'll only know for sure when you program crashes.
Actually you can take the above reasoning even further. Suppose you have a routine of type String -> String
. What can you say about it just based on its type? Hardly anything since all computation is essentially just transforming sequences of symbols into other sequences of symbols. There are as many implementations that pass the type checking as there are possible programs. But if you generalize the type into a -> a
I can deduce what the routine does since there is only one possible implementation: take a parameter, do nothing with it and return it as the output. So using generics reduces code duplication, increases software safety and correctness and further helps reason about programs.
Soz that this was so long, but following Mark Twain, I just didn't have time to write anything shorter.
Viewing a single comment thread. View all comments