7 ms·
Apparently, the author of this blog post had a change of heart: https://memo.barrucadu.co.uk/blub-crisis.html https://memo.barrucadu.co.uk/blub-crisis.html >
by kjksf 6y ago
Apparently, the author of this blog post had a change of heart:
https://memo.barrucadu.co.uk/blub-crisis.html https://memo.barrucadu.co.uk/blub-crisis.html
> I have realised in recent conversations about programming languages, and in reflection of my very negative and kind of arrogant blog post about Go, that I have become trapped by the Blub Paradox. I have become dismissive of non-Haskell languages. I think in Haskell. Languages less powerful than Haskell are obviously too limited to get any real work done in, and languages with more advanced features than Haskell (like dependent types) are really just weird and not actually solving a problem I would ever face.
> The arrogance! Such a know-it-all!
> I have decided to call such a realisation a “Blub Crisis”. Haskell is my Blub. The only solution is to become proficient—actually proficient—in a different language, and once again learn a new way of thinking.
- jonahx 6y agoI thought the criticisms and praise, and the article's Good/Neutral/Bad structure, were fair and thoughtful on balance. It didn't read as arrogant to me.
- panpanna 6y agoIt did to me. He slams go for not doing stuff the Haskell-way (e.g. pure code vs effectful code). This is not how you approach new things
- eptcyka 6y agoThat is a single dubious point amongst some serious and in my opinion legitimate issues with the language.
- scottlocklin 6y agoComplaining about strict evaluation, the std lib not doing what he wants it to, the type system, the lack of heap profiler/threadscape, and .... demanding Golang handle zero values in his preferred way is basically him whining it ain't Haskell. I could blubber about it not having power conjunctions or self intervals or whatever if I wanted Golang to be J, which would be a similarly moronic roster of complaints. In reality golang is a basket of compromises like any other programming language. There's vastly more good stuff built in it than Haskell, despite Haskell being older and more theoretically amazing, so they must be doing something right. His only criticism that resonated with me was go get defaulting to head, which befuddled me when I first saw it, but that's a compromise too; one oriented to the large codebases that golang is designed for. It's actually a pretty good compromise compared to the propeller head Haskell dork "Things break backwards compatibility in Haskell, and the users just update their code because they know the library author did it for a reason." -aka this appears to be a statement from an academic wanker who obviously never had to ship on a timeline in his entire fucking life.
- simiones 6y agoThe type system complaints are somewhat in the area of "it should be more like Haskell", but the debugger, heap profiler and thread debugger ones are certainly not. Golang has extremely basic tools for anything beyond formatting/compiling compared to most modern languages. This is just a limitation of the current ecosystem, not something you can say has tradeoffs (except of course for the Go team's time/prioritization of features). Delve is getting better, but it has a LOT of ground to cover before it is half as useful as gdb or a java/C# debugger. Same goes for the profiling tools, especially on the CPU side.
- dmitriid 6y agoI've never really done Haskell, but I have Erlang, Java, C#, JS, TS and Erlang under my belt. I agree with everything the author said after having spend some time with Go.
- gwd 6y ago> He slams go for not doing stuff the Haskell-way (e.g. pure code vs effectful code). Heck, I come from a C background, and that's a complaint I have about Go. Sometimes you want to have a function accept a pointer to a large structure to avoid copying, but have the compiler prevent you from making any changes. In C you'd write "const"; in Go there's no way to do that.
- panpanna 6y agoSure, const is great to have. But Haskells view on this topic is far far more opinionated than just supporting 'const'.
- deleted 6y ago[deleted]
- Sharlin 6y agoI've never written Haskell or another pure functional language more than a couple of lines, but the more I write code the more convinced I become that the ability to reason about mutability and side effects is a major force multiplier in writing robust software.
- Chris_Newton 6y agoI agree that being able to reason about mutability and other effects is useful. However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. In a sibling comment, gwd mentioned const in C, which is one example of something in between. Rust’s ownership semantics and borrow checker are another.
- pwm 6y ago> However, that doesn’t necessarily imply an all-or-nothing approach where either you’re in a pure function or you can do anything with anything. To elaborate this point I'd say that the most important practical use of all that "monad mumbo-jumbo" in Haskell is that you can tag your functions with what they can and can't do and then the type system tracks this for you: -- pure function f1 :: Text -> Int -- can fail f2 :: Text -> Maybe Int -- can read from some MyEnv record f3 :: Text -> Reader MyEnv Int -- can keep a set of bool as state around f4 :: Text -> State (Set Bool) Int etc... and of course to go nuclear: -- can do anything f5 :: Text -> IO Int The tracking part is that you can't call f5 from within f1, the type checker says no. It enforces separation between all these various effect boundaries. Also we don't have to stop here. A natural next step is defining exact effects one is after. For example say I want my function to be able to get some entity from a DB: -- any type that is an instance of Entity can identify itself by uuid class Entity e where identify :: e -> UUID -- The effect we want, ie. get an entity via its uuid class (Monad m, Entity e) => GetEntity e m where getEntityById :: UUID -> m (Maybe e) now we can say things like: data User = MkUser {uId :: UUID, uName :: Text} -- a User can identify itself instance Entity User where identify = uId -- as User is an Entity so we can get it via its uuid (if it exists) getUserById :: (GetEntity User m) => UUID -> m (Maybe User) getUserById = getEntityById Also notice how getUserById does not say anything about IO or a DB. All it states is that whatever context it will run in that context must know how to get a user via its uuid. You can then plug in whatever actual context you want, say: newtype Prod a = MkProd {unProd :: ReaderT ProdDB IO a} deriving newtype (Functor, Applicative, Monad, MonadReader ProdDB, MonadIO) -- get a user from a DB for real instance GetEntity User Prod where getEntityById :: UUID -> Prod (Maybe User) getEntityById eid = do ProdDB {..} <- ask -- query the DB, etc... or newtype Mock a = MkMock {unMock :: State (Map UUID User) a} deriving newtype (Functor, Applicative, Monad, MonadState (Map UUID User)) -- get a user from a mock DB instance GetEntity User Mock where getEntityById :: UUID -> Mock (Maybe User) getEntityById eid = gets (Map.lookup eid) All in all the programmer have fine-grained control over what various parts of their code can or can't do.
- dragosmocrii 6y agoMy Blub language has been PHP. While the language has been getting better over the years, especially with the introduction of types, I still felt at one point that I wasn't growing. I had a try at Haskell, and failed miserably. I tried OCaml, but still something felt unnatural to me, although what really intrigued me was the sound type system and the guarantee that if it compiles, then it's probably going to run well. I then tried Elixir, and I love it. I think Elixir is a wonderful transition language, but something that I wouldn't mind keeping close in my toolstack. The Actor model, immutability, pattern matching, meta programming, these are all concepts that uppended my way of thinking. PHP/JavaScript array sort functions feel so weird to me now for doing the sorting directly on the variable. But to be honest, I wish Elixir had types. I don't trust myself writing functions that can return different things.
- eru 6y agoErlang has some type annotations. Not sure whether they made it over to Elixir?
- ghayes 6y agoDialyzer is fully integrated into Elixir, yes. But again, it’s optional typing.
- innocentoldguy 6y agoI know how to use Dialyzer and am quite proficient with it. I cannot say, however, that it helps me in any way. I think strong typing is a crutch for bad programmers and I've yet to encounter anything in my 30+ years of programming to change my mind.
- eru 6y agoThere's two sides to it: First, there's only so much I can hold in my brain at once. If the computer can do some of the tedious busy work, let it. Second, the first perspective talks about catching errors and oversights. A sufficiently non-bad programmer could make do without. But static typing also allows for some programming techniques that wouldn't work without. As a silly example, Haskell makes heavy use of overloading-by-return-type. You just don't the information about what return-type is expected available dynamically, it needs to be static. There's also lots of optimizations that are safe only when the compiler knows more about your code. (Of course, a sufficiently non-bad programmer could write directly in the machine language of every processor she's writing code for..) In practice, typing helps me a lot with eg exhaustiveness checking for my pattern matches. The type system that dialyzer exposes is pretty weak. So not a good standard to measure all of typing against.
- quickthrower2 6y agoDefinitely! I couldn't get my head around why people like untyped languages, but I keep an open mind on it. I won't close off that they could be better, if the right patterns/practices are used (whatever they are!)
- eru 6y agoWell, if your alternative was 90s style Java or C++ static typing, Python-style dynamic typing looks comparatively less insane. As soon as you have algebraic data types and parametric polymorphism, static typing is less onerous, so dynamic typing is less appealing.
- rwmj 6y agoAnd especially type inference.
- eru 6y agoYes. Ideally something as powerful as Hindley-Milner or similar. But even the weak sauce versions in Go (or recent Java or C++) are a boon to developer ergonomics.
- Twisol 6y agoJava's is particularly weaksauce, and has problems chaining inferences within even the same expression, but it's definitely way better than not having it at all.
- quickthrower2 6y agoI liked 90s Java at the time. ;-) well the alternative seemed to be c++ or vb or Perl and I didn’t know about python.
- pizza234 6y ago> I couldn't get my head around why people like untyped languages What do you mean exactly with "liking" untyped languages? I personally program mainly in both a ("cognitively demanding") typed and an untyped languages, and they have different use cases. For relatively small programs, untyped languages are much faster to develop. A program I wrote yesterday in a few hours would have taken 2 to 4 times as much in a typed language. On large libraries (I consider gaming engines as so), common wisdom suggests that typed languages make the project easier to manage (modify and so on). There's obviously a wide range of use cases in between.
- Cthulhu_ 6y agoRecently I've become a bit jaded, because I see flaws and the like in every language I've used; I (like to think I) don't have a "blub" language. Mind you I've never gotten along with pure functional languages. I've mostly done CRUD applications and I'm not sure functional languages are appropriate for that use case.
- pdimitar 6y agoFP languages like Elixir are perfect for CRUD apps IMO (Clojure too but it lacks the runtime guarantees of Erlang's BEAM VM so to me that's a no-go). Reason being: they are immutable in general but allow you escape hatches that you can relatively easily identify in your code if you need to troubleshoot.
- barnacled 6y agoWhile I think there's some sense in the analogy and you get real insights using new languages, I do find that 'beating the averages' article really unconvincing. Firstly there's the obvious observation that Y Combinator companies very rarely use lisp, but there's also really a lack of any solid evidence of any kind anywhere that language choice has such a big impact. I am a fan of exploring languages and making a good choice for the problem at hand and always remaining open-minded but I can't stand the religious flame war side of it and I really do not think that article helps, at all. To me languages are always a trade-off between abstraction and control, to which each problem has an appropriate range of languages to apply. I also think the concept doesn't apply here as go is certainly less powerful and has fewer abstractions than Haskell (by design) - so if anything it is the 'blub' language* according to the article here (my point being not to criticise go but rather to point out how silly the beating the averages concept is). I don't think his original piece was arrogant, I think this is something of an overreaction and a problem with assessing any language - adherents meeting criticism with 'you just have to use it more' can use that excuse indefinitely. Better to address individual points. * I love go and contributed to the core compiler back in 2011/12 so this isn't an attack on it.
- the_af 6y agoSuch a weird thing to frame this in terms of the Blub Paradox. Regardless of what you think about the paradox, this is what it states: > But when our hypothetical Blub programmer looks in the other direction, up the power continuum, he doesn’t realize he’s looking up. What he sees are merely weird languages. He probably considers them about equivalent in power to Blub, but with all this other hairy stuff thrown in as well. Blub is good enough for him, because he thinks in Blub. It's very, very hard to argue Go is "up the power continuum" from Haskell, or that Haskell is a Blub language compared to Go. Everything else can be debatable, but surely not this. He could have simply said "I was arrogant about Go, and need to look at it from a fresh perspective instead of comparing it to a language I'm more familiar with", no appeals to Blub needed.
- JackMorgan 6y agoI think he's not saying Golang is up the power continuum, but that languages like Idris and Coq are up the power continuum. He doesn't bother learning those because he's "stuck".
- the_af 6y agoI think you're right! I misread it. Also interesting: it's his only article tagged Go, from 2017. He never mentions Go again. Since he has several more articles about Haskell, I wonder if he eventually quit his job, or whether he simply didn't have anything else to say about Go.
- AnimalMuppet 6y agoThe Blub Paradox is flat-out wrong. To see why, just look at Haskell and Lisp. When a Lisp user looks at Haskell, they are sure they're looking down, because Haskell doesn't have macros. But when a Haskell type (pun intended) looks at Lisp, they are also sure that they're looking down, because Lisp doesn't have a decent (Hindley-Milner) type system. This situation - two languages, each sure that they're above the other - shows the problem. You cannot rank languages on a one-dimensional axis called power. Another way of getting there is to ask: Power? Power for what? For writing programs. What kind of programs? General programs? I've never written a general program in my life. I've written a bunch of specific ones, though. What I care about is power to write this program - the one I'm currently trying to write. (Why do I care about a language's power to write a program that I'm not trying to write?) Instead, think in terms of yak shaving. What are the yak shaving aspects of the program I'm trying to write? Think of that as a vector in a multi-dimensional space. Think of languages as branches on a tree. Which branch extends farthest in the direction of the yak-shaving vector? Use that language. But you have to have kind of an expanded idea of what "yak shaving" means. In particular, if you pick a "non standard" language, training your team becomes part of the yak shaving.