3 ms·
Of course, they conservatively added the most idiotic way of formatting dates as strings (while knowing other methods exist). And, while the whole bunch of othe
by HackerThemAll 3y ago
Of course, they conservatively added the most idiotic way of formatting dates as strings (while knowing other methods exist). And, while the whole bunch of other languages would call a method string.startsWith("a"), they use hasPrefix. This language is a mix of half-baked concepts and utter trolling. If I have to learn a lang with an awkward syntax, I'd prefer Rust, Julia, Erlang, Elixir or Haskell. Go is no-go. It's not even widely used at Google, its creator. So no, thanks.
- WorldMaker 3y agoAlso, why would force error returns without also including some sort of nice Monadic do-notation or Monad-inspired combinator syntax sugar in the 2020s? We've known for decades now how do that better. I also think that Go looks like a practical joke that escaped some INTERCAL-like satire committee in the 1970s.
- hollerith 3y agoYou probably mean sum types and convenient syntax for testing and de-structuring sum types.
- WorldMaker 3y agoNo I specifically meant what is often called the Either or Result Monad. These are often implemented as Sum types, but they also follow the Monad laws and supports things like monadic binding/transformation/combination and benefit from syntax sugar like Haskell's "do-notation"/OCaML family's "computation expressions"/the "async/await" pattern of so many other languages now. Good sum types destructuring would probably also be useful in more languages like Go, but many languages today provide "async/await" pattern syntax benefits without anything at all like "proper" sum types. Sum types are "merely" a possible implementation detail of the Monad and it's the Monad laws that empower some things beyond just sum types.
- hollerith 3y agoWhy pick on Golang, then? Rust doesn't have a monadic interface to side effects and "errors" either. Nor do the vast majority of the other newer languages.
- WorldMaker 3y agoRust uses a sum type for most errors (Result<T, Error>) and there are common macros such as "error-chain" that apply a monadic approach to binding/combining them (or chaining them, as the preferred nomenclature in that case). Exception-based languages don't look monadic at first blush, they definitely aren't Sum types, but try/catch is one of the earliest and oldest of the monadic binding/combining approaches, even if it isn't often thought as such (and is barely considered more than goto/switch). It's far more obvious when you start to realize the intersection of async/await and try/catch is a working monad (and how that is reflected in Task/Promise monad instances). Golang is the obvious odd one out where every other line of "best practice" code is `if err != nil` and the only other advice is "well you could just ignore errors". try/catch doesn't ignore errors, it just looks like it. Rust error chaining doesn't ignore errors, it just looks like it. Golang gives you the choice between micro-managing errors or BASIC-style "ON ERROR RESUME NEXT" and I cannot get anyone to convince me why this isn't either a practical joke or an intentional throwback to writing code like it is the 1970s all over again (even VB6 had better options than "ON ERROR RESUME NEXT", even if they maybe weren't used as often as they should be in some legacy 1990s/2000s codebases).
- hollerith 3y ago>every other line of "best practice" code is `if err != nil` and the only other advice is "well you could just ignore errors". You have a valid point there, but it hurts my ears a little for you to use the word "monadic" or "monad" to make the distinction between how the way Golang handles errors differs from how other modern language do it. To me, for a language to "have monads" requires the type system to give the programmer the ability to distinguish between a value type, e.g., an integer, and a computation that produce a value type. Haskell's type system for example uses `Integer` to refer to the former and, e.g., `IO Integer` to refer to that latter. And clearly by that definition, Rust and most other modern languages just don't have monads, i.e., don't have monadic types (and consequently don't support a monadic programming style) -- unless perhaps Rust's macro system can be used in some complex way to define the monadic-computational types, but I've never seen it used that way. BTW, I'd actually go further and say that to get the benefits of monadic style, the IO monad or whatever the language calls it must be the only way to perform side-effecting computations (though there is a little wiggle room on the definition of side effect here). To be more precise, the terminology I prefer is that a monad (in the context of programming languages) is a type that obeys the 3 monad laws: https://wiki.haskell.org/Monad_laws https://wiki.haskell.org/Monad_laws. There are other ways besides a monad for the type system to distinguish between a value and a computation producing a value; Explicit continuation passing is one such way: whereas in Haskell you'd read a character from standard input with `main = getChar >>= \char -> do something with char`, in a language that uses explicit continuation passing, you'd write `main = getChar (\char -> do something with char)` where in this language getChar takes one argument, which happens to be a continuation argument. But all the languages I know about that let the programmer use the type system to distinguish between a value and a computation producing a value use the monadic style to express that distinction (rather than something like explicit continuation passing) so I tend to use "monad" and "monadic" to refer both to the specific thing that obeys the 3 laws and for the deeper programming-language property.