Live data from Hacker News

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

quuxplusone.github.io

211–220 of 406 posts

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

#211

Earlier quoted context omitted.

Sure, you can build your own object and pass the 'this' pointer around manually. You could use C for everything, and tediously do everything again that objects do for free. But why? There's a lot of object-hating going around. Its silly. Use objects to encapsulate functionality, they are good at that and everybody understands what it means.

What you call “for free”, I call implicit. Passing it as function arguments makes it explicit. You don't need to “hate” “objects” to prefer the explicit over the implicit.

I think you could apply your argument to any use of objects, unless there are virtual methods involved. So you probably would have to be pretty generally against the use of objects to agree.

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

#212
I had to look up what memoization is- guess I’m getting rusty? But it turns out it’s just a new word for an old concept (caching).

I’ve always done it this way:

double calculation(double arg) {

  thread_local bool prev_arg_valid = false;
  thread_local double prev_arg;
  thread_local double prev_result;

  double result;
  if(prev_arg_valid && prev_arg == arg)
    result = prev_result;
  else {
    //do the calculation 
    result = ...;
    prev_arg = arg;
    prev_result = result;
    prev_arg_valid = true;
  }
  return result;
}

Doing it this way is something you would only ever do if you knew beforehand the user would be asking for the same value over and over, but it’s clean and invisible to the calling code and doesn’t break your assumptions about what the function is going to return.

The memoization pattern is valid too of course, I just find it interesting I’ve always done the same thing when advantageous but in a different way.

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

#213

Earlier quoted context omitted.

But if you're passing a state object around, you might as well use a class, no? Admittedly simplifying a bit, an instance method is a function that implicitly takes "this" as the first argument.

Let's use C and C++ as an example. What does the code look like? myobj.cool_func(1,2,3); // C++ cool_func(myobj, 1, 2, 3); // C Is this better? If you use a vanilla C++ style class then the class definition is in the header. All changes to the class require a recompilation and break the ABI of the class. This means you basically cannot release patch versions of your library because consumers cannot link against it if…

In C you would do

    my_lib_cool_func(myobj, 1, 2, 3);
so you don't pollute the global namespace excessively. Having it accessed through the object avoids that.

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

#214

Earlier quoted context omitted.

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.

Sure, you can build your own object and pass the 'this' pointer around manually. You could use C for everything, and tediously do everything again that objects do for free. But why? There's a lot of object-hating going around. Its silly. Use objects to encapsulate functionality, they are good at that and everybody understands what it means.

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 will be 1/10th the size and have 1/10th the semantic programming language elements. That is why you see ‘object-hating’ all over the industry. It hasn’t lived up to its promise.

Objects aren’t simpler, inherently. It’s just what you know, today, and you’re unwilling to acknowledge your biases.

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

#215

Earlier quoted context omitted.

I like the approach Wouter van Oortmerssen uses in Lobster: class Animal: alive = true class Cat : Animal def hello(): print "meow" class Dog : Animal barked = 0 def hello(d::Dog): print "bark!" barked++ let d = Dog {} d.hello() let a:Animal = d a.hello() In other words, A.B(C) is just syntactic sugar for B(A, C), and class definitions are just syntactic on top of that. The relation between OO and regular functions a…

This is also the approach taken by Nim and D, and it is known as the UFCS (Uniform Function Call Syntax)[0], and I agree - it's the best of all worlds. [0] https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax

I think Swift does this too?

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

#216
post #3

Also known in python as "if your class has only two methods, one of which is init, it's a function" in the "stop writing classes" https://www.youtube.com/watch?v=o9pEzgHorH0 EDIT: typo, changed link

At the same time, if your function has an expensive initialization step that only needs to be called once (and doesn't change between calls), then the pattern of using `__init__()` + `__call__()` can be very nice.

I would consider this pattern:

    def x():
        expensive precompute
        def y():
           cheap stuff
        return y
It's a matter of taste I guess.

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

#217

Earlier quoted context omitted.

that only works if you are in a context where you can deduce the type from ctor arguments, which is definitely not all cases (for instance, storing as a member and initializing in a ctor, etc...)

You can then specify the function pointer type, although mildly inconvenient. If you want to use lambdas though, then yes, you are out of luck as their type is unnameable.

but that fails as soon as you have a case where you want to pass an algorithm implementation that does have state. That was my point - whenever I assumed that I would not have state... well I ended up needing to refactor everything because I ended up needing to add a new strategy that did require some state later.

In the context of C++, struct / class types are more generic that function pointers and there's no real shortcut around this - that's how the language is specified.

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

#218

Earlier quoted context omitted.

Sure, you can build your own object and pass the 'this' pointer around manually. You could use C for everything, and tediously do everything again that objects do for free. But why? There's a lot of object-hating going around. Its silly. Use objects to encapsulate functionality, they are good at that and everybody understands what it means.

What you call “for free”, I call implicit. Passing it as function arguments makes it explicit. You don't need to “hate” “objects” to prefer the explicit over the implicit.

I don't find all that much of a difference between notations like set.map{...} and map(set){...}, so at that point I suppose it really is just aesthetic preference.

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

#219
post #185

Earlier quoted context omitted.

Why? The main advantage of passing a state as an argument is letting the user control the state. If you need an array as state, the user might want to put the array on the stack, or the heap, or in static memory, or protected behind a mutex somewhere... It doesn't really matter that much how things are actually implemented: most languages are flexible enough that you can do this with a class or a function or even imp…

If we’re talking about an algorithm as a class, the state managed by the class is algorithm state, not the data the algorithm acts on. The data the algorithm acts on should probably be passed as a parameter regardless of whether the algorithm is implemented as a class or top-level function.

> If we’re talking about an algorithm as a class, the state managed by the class is algorithm state, not the data the algorithm acts on.

I was only talking about algorithm state here. Check, for example, how the C++ string searching algorithms work to get a feeling of how these APIs work in the wild. For an example of this gone wrong, look no further than C++ stable_search, which does not let the user reuse the merge sort buffer across searches.

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

#220

Earlier quoted context omitted.

What you call “for free”, I call implicit. Passing it as function arguments makes it explicit. You don't need to “hate” “objects” to prefer the explicit over the implicit.

I don't find all that much of a difference between notations like set.map{...} and map(set){...}, so at that point I suppose it really is just aesthetic preference.

Classes usually have a more complex state than the state passed to utility functions, which is a reason I'd be incline to use e.g. a struct as a state vs a C++ class. Makes it harder to write bad code.
Post reply on HN