[-] expr@programming.dev 2 points 1 week ago

Ah I see, my bad. You mentioned Ruby on rails and GraphQL so I assumed you were talking about some kind of MPA situation.

Yeah htmx doesn't replace data APIs for sure. Still not a fan of GraphQL for that purpose for the reasons above. There's a lot of good options for RPC stuff, or even better, you can use message queues. GraphQL is just a bad idea for production systems, IMO.

[-] expr@programming.dev 2 points 1 week ago

I was replying to someone talking about GraphQL and Ruby on rails, not the OP of this post.

[-] expr@programming.dev 2 points 1 month ago

Why are you such a piece of shit? Or is this just bait?

[-] expr@programming.dev 2 points 1 month ago

Sure, perhaps it's possible that I saw an unusually high amount of apologists, but I'm saying that it happened enough times and consistently enough that it prompted me to block them before I even knew anything about them, which I think at least says something. I won't claim to know what the majority opinion there is, but I don't think it's a stretch to say that it's an abnormal amount.

[-] expr@programming.dev 2 points 1 month ago

I made this mistake for ages because Haskell is so popular and it's functional and pure, but it's not actually a requirement for functional languages to be pure. OCaml isn't.

I didn't say that FP languages have to necessarily be pure, just that FP languages tackle the problem of mutation by arranging programs such that most things are typically pure and side effects typically happen at the periphery (logging is probably the one exception, though). This is true even in FP languages that allow arbitrary side effects in functions, it's just not enforced by a compiler.

I agree Rust code has a different feel to OCaml code but that's because it makes some things easier (e.g. mutation, vectors). You still could write Rust as if it was OCaml (except for the lack of currying), it's just that nobody does that because it sucks.

That's the entire point, though. It's all about what the language emphasizes and makes easy to do. If it's unnatural to write a functional program in Rust and no one does it, then it's not really reasonable to call it a functional language. Writing functional programs is not idiomatic Rust, and that's okay.

[-] expr@programming.dev 2 points 2 months ago

It's funny you mention Reddit because there was a subreddit dedicated to making fun of shit "centrist" takes like yours: https://www.reddit.com/r/ENLIGHTENEDCENTRISM/.

The fact is that politics in the US is skewed so far to the right that the options are center-right (Democrats) or far, extremist right (Republicans).

[-] expr@programming.dev 2 points 2 months ago

Minor nit: Kotlin is decidedly not a functional language.

Design patterns in OOP exist purely to solve the problems created by OOP itself. If you have a language with proper ADTs and higher order functions, the need for traditional design patterns disappear since the problems they solve are first-class features baked into the language.

The first-class replacement for the Strategy pattern (and many other patterns such as the Visitor pattern) is sum types (called enums in Rust).

[-] expr@programming.dev 2 points 2 months ago

This is a very common toy example we use in Haskell, though honestly this OOP version leaves a lot to be desired, comparatively

The issue is that it tries to shoehorn separation of data and functions on data into a paradigm that's fundamentally about fusing those two things together.

Here's the Haskell version. Note how much simpler it is because data and functions are separate:

data Expr
  = Lit Int
  | Add Expr Expr

eval :: Expr -> Int
eval expr = case expr of
  Lit n -> n
  Add a b -> eval a + eval b

print :: Expr -> String
print expr = case expr of
  Lit n -> show n
  Add a b -> "(" ++ print a ++ " + " ++ print b ++ ")"

Typescript can do something similar:

type Expr = {
  kind: 'Lit',
  value: number
} | {
  kind: 'Add',
  left: Expr,
  right: Expr
}

function eval(expr: Expr): number {
  switch(expr.kind){
    case 'Lit': return expr.value;
    case 'Add': return eval(expr.left) + eval(expr.right);
    default:
      const _impossible: never = expr;
      return _impossible;
}

function print(expr: Expr): string {
  switch(expr.kind){
    case 'Lit': return `${expr.value}`;
    case 'Add': return `(${print(expr.left)} + ${print(expr.right)})`;
    default:
      const _impossible: never = expr;
      return _impossible;
}

Both the OOP approach and Typescript itself struggle with additions to the algebra composed of different types, however. For example, imagine extending it to handle booleans as well, supporting equality operations. It's difficult to make that well-typed using the techniques discussed thus far. In Haskell, we can handle that by making Expr a GADT, or Generalized Algebraic Data Type. That article actually already provides the code for this, so you can look there if you're curious how it works.

[-] expr@programming.dev 2 points 3 months ago

Last 3 years has been working on large backend web services in Haskell and Postgres, with some shell scripting thrown in here and there.

Before that, it was a mix of Python, Typescript (React), Rust, and C++.

[-] expr@programming.dev 2 points 3 months ago* (last edited 3 months ago)

Hitting children is always abuse, no matter the country or culture. Just because a society might deem it socially acceptable doesn't make it less abusive.

It was socially acceptable to hit children in the United States decades ago. My grandparents whipped me with a belt. That was absolutely abuse. It was abuse then and it's abuse now, even if no one batted an eye at the time. Anyone hitting their children is physically abusing them.

[-] expr@programming.dev 2 points 3 months ago

Yeah. Anduril has tried to hire me multiple times as well as well as a number of people I know (their software is written in Haskell, which is a somewhat niche skill set).

Every time I've told them absolutely not.

[-] expr@programming.dev 2 points 3 months ago

It generally works with a wide variety of delimiters. There's a widely used plugin to make it work with even more, including language-specific keyword pairs.

view more: ‹ prev next ›

expr

joined 1 year ago