Live data from Hacker News

A Defer Mechanism for C

gustedt.wordpress.com

51–60 of 248 posts

Re: A Defer Mechanism for C

#51

Re: Should object values be captured? The results from 387 responses (to a Twitter poll) show a 2:1 preference for the value being read at the time the deferred statements are executed (66.9%) rather than when the defer statement encountered(33.1%). Since both options - by value and by reference - may be viewed as reasonable or desirable, neither should be a default. Instead, they both should be using a special synta…

The ^ is already taken in context of "C lambdas" though (hoping that if C ever gets lambdas it will simply adopt clang blocks instead of a C++ like syntax): https://clang.llvm.org/docs/BlockLanguageSpec.html

Aye, I've seen that.

IMO it would've been better (read, cleaner) to merge lambdas and function pointers into a single language construct. Throw in the partial application too and we'd be have a natively supported concept of a "callable" instance -

  void foo(int tick);
  void bar(int tick, int tock);

  void do_something( void (* progress)(int tick) );

  do_something( foo );
  do_something( bar(,1) );
  do_something( void (int tick) { /* lambda */ } );
The syntax is approximate, but for the code that is using callback-based flows this would've been very handy.

Re: A Defer Mechanism for C

#52
post #9

Earlier quoted context omitted.

Destructors are not called randomly.

As replied by someone else, by 'random' I did not mean really 'randomly', because the machine is determinist and follow a logic. But more that there is so much magic and abstractions that it is very hard for a dev to have a clear view of what is going on and what to expect. He has to 'guess' instead of just read the code. For that, I guess that it is similar to the current question of accountability of decisions made…

> As an example of my point, I would refer to the 'garbage collection' issues of a language like 'java'

Two languages could hardly be less alike than Java and C++ - the latter is not garbage collected and where destructors are called is completely predictable.

Re: A Defer Mechanism for C

#53
post #23
post #6

Earlier quoted context omitted.

> One of the key interest of C compared to more recent languages is that everything is explicit. There's nothing implicit about defer.

Deferred actions are not explicit at the exit points. That's quite implicit. You can no longer reason about a local piece of code; you now have to know its lexical nesting up to top level to see if it's inside a guard block that might trigger hidden behavior.

I wondered about this. Say I have a block, at the end of which I free a bunch of memory. I also have a bunch of other exit points within the block (mostly for catastrophic errors, say). Would a deferred free only apply to the outer scope? Because if so, I really don't see the point at all.

Re: A Defer Mechanism for C

#54

I’ve always considered “defer” an inelegant kludge in comparison to RAII for automatic cleanup of resources. It’s surprising that the C standards committee is considering adding that to the language. Then again, nearly none of the syntactic C features post-C89 have been very compelling or widely adopted.

RAII is a special case of defer, due to how it abuses constructors and destructors to hook into the points of entering and exiting scope. You could write a RAII implementation in terms of defer but not the other way around.

RAII doesn't help with a generic pair of init and deinit functions, such as malloc() and free() for example, unless you wrap your mallocs into "memory objects" or something. You can't do anything with RAII unless you wrap your stuff into objects which just forces the OO crap on everything regardless of whether it's a good fit for the OO paradigm.

But even in RAII, classes are merely just a way to bind init and deinit together. As a result, you can't "forget" to free the resource. (Unless you use the new operator...) But this is merely an interface issue: defer could be of the form

    void *block = defer malloc(SZ) with free(block);
or something similar that requires the init and deinit calls to be part of the defer expression itself.

Nevertheless, a defer is clearly a useful language feature that C actually lacks. Currently C doesn't offer the code any attaching points to the lexical scope of the program. You can fake it with a special for(;;) statement but it's a kludge and even by wrapping it into a macro it's very hard to make it a generic solution.

Re: A Defer Mechanism for C

#55
post #28

Why is there a special guard keyword? Scope limits are already clear.

> The guard statement allows for a library implementation. Foregoing the possibility of a library implementation, a possible design choice could be to eliminate the guard statement as it would eliminate the need for an additional reserved keyword and the requirement for programmers to create guarded blocks around deferred statements. If the guard statement is not used, the proposed changes to the behavior of the break statement would likely be eliminated as well (see Appendix K).

Re: A Defer Mechanism for C

#56
post #33

Earlier quoted context omitted.

I made no comparison between “defer” and the current C situation. In comparison to RAII, “defer” as a language feature is a kludge. Mainly because RAII completely solves the problem of correct resource cleanup for API users while “defer” does not.

RAII is an idiom, not a language feature. Destructors might be the language feature, but they have their own issues and caveats. So I don't see the comparison...

I think it's quite reasonable to compare defer and destructors, in that case.

Destructors probably cannot be usefully imported into C while preserving the simplicity of the language: then you'll want at least unique_ptr to manage your memory with destructors, then probably shared_ptr, and some ownership semantics as you pass those around, et cetera. In that sense, defer strikes a balance between simplicity and usefulness. However, there is still a comparison.

Re: A Defer Mechanism for C

#58
post #6
post #2

Despite being convenient,I have the feeling that it might be a bad idea. One of the key interest of C compared to more recent languages is that everything is explicit. With a finger you can follow the code as it runs and know exactly what is going on and when exactly. At the opposite, there is c++ that does a lot of things automagically. And it is often hard to understand why you suddenly get a segfault out of blue,…

> One of the key interest of C compared to more recent languages is that everything is explicit. There's nothing implicit about defer.

Every defer statement is ultimately pushing a lambda into some stack that is executed when the defer block is exited. With an exception of setjmp/longjmp, I can't think of an existing C construct with similar run-time complexity.

Re: A Defer Mechanism for C

#59
post #46

In its current form, this is really stupid, because of something like this: guard { for (int i = 0; i Now the compiler has to: 1. implement some side of capture/closure mechanism to keep all the 'i's to the end of the guard block 2. do dynamic allocation to store the closures so they can be executed at the end did the scope 1 seems like too much work for such a feature, and 2 is a massive no. Implicit dynamic allocat…

I got the impression that the proposal still has some aspects of the design that are open for discussion, including whether it should be static or dynamic, and whether it should capture the variables by value or by reference. (These are discussed in pages 13-16)

Re: A Defer Mechanism for C

#60

Zig has defer and errdefer. C should just steal however Zig does it.

I love Zig, and I'm looking forward to it continuing to mature. I've been waiting for a specific compiler TODO to be resolved (something like initializing union bitfields) that (at least as of 0.7.0) wasn't yet implemented, because I was using it in a toy OS for some GDT stuff.
Post reply on HN