Live data from Hacker News

The use of `class` for things that should be simple free functions

quuxplusone.github.io

271–280 of 406 posts

Re: The use of `class` for things that should be simple free functions

#271
post #229

Earlier quoted context omitted.

Seems like kind of a meaningless gesture to pass in your own “this” just because you don’t like OOP. If you need a class, why not write it the idiomatic way?

I didn't down-vote you, but in my opinion it's not meaningless because it makes it inherently more testable. Try testing an opaque class without any accessibility into its state. It is much more difficult. If it takes in the state, performs an operation, and returns a new version of that state (ideally an immutable copy) then it becomes much easier to test and validate. The reason information hiding is/was advocated…

I see your point, but I 80% disagree with your conclusion.

When you test opaque objects, you're generally not trying to test individual state transitions, you're trying to test that the class's interface adheres to the external promises it makes.

That said, many OOP languages have solutions specifically for when you actually do need to test those internal state transitions. C# for example has the "internal" keyword and allows you to declare friend assemblies, so you mostly get your cake and eat it too, at the cost of not hiding the code from yourself as the module implementer.

Re: The use of `class` for things that should be simple free functions

#272
post #265

I suspect the absense of free functions in Java (which is frequently the first language taught at universities) is a big reason this antipattern is prevalent.

That brings back frustrating memories of moving to Java from day one at university and trying to get up to speed. I remember a bunch of "tips" spreading around the computer lab, all related to IDE and language quirks, in a 100 level class. I hope this isn't still the case, 20 years later? It kind of spoiled me for Java, which made life difficult later when I joined a FOSS project which was built in Java.

After that experience I found returning not even just to functions but also e.g. Pascal procedures was pretty refreshing.

Re: The use of `class` for things that should be simple free functions

#273
post #229

Earlier quoted context omitted.

You don’t agree with an idea so it’s silly? Passing around state via variables is no more tedious than the extra syntax for class definitions, constructors, member variable access, extra semantics related to objects, extra keywords related to visibility, etc. You can encapsulate functionality without objects. There is nothing that you can do with an object that you can’t do with a closure, and the closure version wil…

Seems like kind of a meaningless gesture to pass in your own “this” just because you don’t like OOP. If you need a class, why not write it the idiomatic way?

Because it's like using a while loop to print out each character in a string when you can just do print to print the entire string.

I don't want to worry about external methods modifying state, I don't want to deal with constructors, I don't want to deal with instantiating state or modifying state before I call my function.

My function just takes a state and returns a new state. Simple.

Re: The use of `class` for things that should be simple free functions

#274
post #146
post #138

Earlier quoted context omitted.

i don't think that's correct, afaik typeclasses roughly desugar to passing a record of functions (vtable/"dictionary") at the call site

And that vtable depends on the type, not the value.

i guess there's really two implicit arguments - the value's type, `a` (quantified via forall - the System F "Λ") and its vtable `Show a`... though i guess the vtable is uniquely determined by the type bc in Haskell instances are globally unique

Re: The use of `class` for things that should be simple free functions

#276
post #143
post #115

Earlier quoted context omitted.

It's easy to create an object that pretends to be a function; it's harder to make a function retain state later. I read that as an argument in favour of functions. Implicit state is pain. Making state explicit is a great advantage of fp-style programming IMHO.

I am not sure I understand your differentiation of explicit and implicit state. I believe you refer to Objects that change their internal values over time; in that calling the same function twice yields different results. Of course, such objects can be a pain to use. Objects are all about making state explicit. Constructors connect different primitive values to a higher order concept, goal or task and checks invarian…

I think your Wallet.pay(amount) example argues for a different conclusion than you arrive at.

I have a Wallet with $500 in it. I call Wallet.pay(100). In your approach, it returns a new Wallet with $400 in it. But I also still have the old, unmutated Wallet with $500 in it, which could be referred to by mistake (or by malice). That's probably not the best argument for immutable objects...

Re: The use of `class` for things that should be simple free functions

#277
post #229

Earlier quoted context omitted.

Seems like kind of a meaningless gesture to pass in your own “this” just because you don’t like OOP. If you need a class, why not write it the idiomatic way?

I didn't down-vote you, but in my opinion it's not meaningless because it makes it inherently more testable. Try testing an opaque class without any accessibility into its state. It is much more difficult. If it takes in the state, performs an operation, and returns a new version of that state (ideally an immutable copy) then it becomes much easier to test and validate. The reason information hiding is/was advocated…

If you’re asserting non-public internals of a class, your testing is wrong in the first place. Assert outcomes, not the process.

Re: The use of `class` for things that should be simple free functions

#278

Counter-point: while in many situations this isn't the right approach, it's worth recognizing when this is the right approach, because they can look awfully similar. An example of this is graph searching, e.g. BFS or Dijkstra's algorithm. The typical implementation is a function. But if you make Dijkstra a class, with (say) a function to iterate through nodes, it lets you do several things that would be difficult wit…

None of these situations require an object to do. You can always have a function that takes in an extra ‘state’ argument. You can then do everything you said by passing in the corresponding state values.

Nothing made this as clear for me as using the Nim language, where functions defined as

   proc doThing(x: MyObject; value: string)
can be called both with

   doThing(x, y)
and with

   x.doThing(y)
where x by itself is 'just' a data object, but is treated transparently by the language as having associated functions, setters, getters, etc as if it were a class (even though they can all also be directly called separately).

It's an approach that I find really elegant and that I wish more languages used in some way.

Re: The use of `class` for things that should be simple free functions

#279

Add to that, that sometimes you want to pass procedures or functions to others (I know, crazy, right?). With this "everything must be a class" approach, it becomes needlessly convoluted to do that. If you don't have static methods, then you need to create an object first, for the sake of giving that object's methods to another procedure or function. It makes using the functionality more cumbersome. For usage I'd say:…

Alan Perlis programming epigram #11: If you have a procedure with 10 parameters, you probably missed some.

Re: The use of `class` for things that should be simple free functions

#280

Earlier quoted context omitted.

Though i agree with with your general statement, i think the 1/10th the size figure is a bit disingenuous. At least the cases where i've gone from the unnecessary OO style to a simpler function/procedure based solution (in JS, which supports both styles just nice), the code size difference hasn't been anything that great. At most it's been half the size. Which is a lot i think! But not an order of magnitude less. I'm…

For JS, it's best to avoid class as possible, due to this and bind / apply shenanigans. Closure and function return function can be used as substitute, and except for inheritance (which should be avoided too), I haven't found any use case for using class class. Example: function MyList { let data = []; let add = (item) => data.push(item); return { add }; }

> Closure and function return function can be used as substitute

So for every list you have an additional allocation for the add function. It obviously continuously to get much worse as more "methods" are inevitably added. That's extremely inefficient for something that's used often and it's not something JavaScript engines can optimize away. The benefit is also extremely negligible since the closed over values are still implicit in the call to add.

Post reply on HN