Hacker News new | ask | show | jobs
by saurik 702 days ago
Which is really annoying, and makes a ton of templated code in C++ have have to bifurcate on void unnecessarily. They already let me do return f(); in a void function if f also returns void... they should let me declare a variable of type void and the language is going to become a lot more pleasant.
2 comments

Not that familiar with c++ but used to have this thought about both Java and C#. Think I’ve changed my stance on it now though.

If following something like CQS the bifurcation can be thought of allowing “pure” functions and excluding code with a temporal / side-effecting component from higher order code.

Not saying bifurcating on void is the best approach to handle that, but in languages where side effects are a thing something is needed to make sure higher order code and side effecting code mix properly.

This is only relevant to pure languages.

And this doesn’t come anywhere near to properly making that distinction anyway: a non-void function can have all the side effects, and a void function can have no side-effects.

It also does not “make sure higher order code and side effecting code mix properly”, it just makes a subset of likely side-effecting code not mix with higher order code at all.

What are you going to put in that variable?

    void f();
    void v = f();
    void g(a){return a;}
    v = g(v);
Maybe my imagination is failing me, but I can't see how this can do much good without at least polymorphic functions.

   template<range R, regular X, invocable<range_value<R>, X> F>
     requires same_as<invoke_result_t<F, R, X>, X>
   auto fold(R&& range, F f, X accumulator) {
      for(auto x: range) 
         accumulator = f(x, accumulator);
      return accumulator;
   }
I can call that with a function returning a custom unit type:

   enum class void_t { Void };

   fold(my_range, [](auto&& elem, void_t) { return Void; }, Void);
But not with void:

   fold(my_range, [](auto&& elem, void) { return; }, void{});
which is very annoying and requires fold to special case 'void' via metaprogramming.
Templates already provide that useful polymorphism;

    template<typename T>
    T callWithState(auto f) {
        auto old = globalState;
        globalState = whatever();
        T out = f();
        globalState = old;
        return out;
    }
(forgive any syntax errors, my C++ is very rusty...)
The void value. E.g.

    fn f() {}
    let mut v: () = f();
    fn g(a: ()) { a }
    V = g(v);
> Maybe my imagination is failing me, but I can't see how this can do much good without at least polymorphic functions.

Sure, it doesn’t do much useful to C save make void ever so slightly less wonky.