Hi Bruno, Am Do., 9. Juli 2020 um 22:16 Uhr schrieb Bruno Haible <br...@clisp.org>:
> > a number of modules (like the hash module or the list module) allow > > the user to specify callbacks (e.g. a comparison function). > > Unfortunately, these procedures do not take a context parameter, which > > can be a problem because C lacks closures. > > Is this a practical, actual problem, or only a theoretical one? It is a practical one; in a computer algebra application, I have lots of small entities (two words each), whose sort order is determined by the extra data. > I would hesitate to change (or duplicate) public API, when there is no > practical need. > > Note that the lack of context can be remedied by > - use of per-thread variables, or That's doable, but thread-local variables are like dynamically scoped variables, which makes reasoning about the program a bit harder. Moreover, for decent speed, native thread locals would have to be supported. > - use of nested functions [1], or I don't want to use non-portable functions. > - storing a pointer to the necessary context in the list elements. In my use case, this would be an increase of 50% in the size of the elements everywhere they appear. > > The original qsort function in stdlib.h has the same problem. Glibs > > has remedied the problem by introducing qsort_r. > > qsort_r is only portable to glibc systems, FreeBSD, and macOS. And yet, > no one has requested a substitute for it in gnulib. IMO this indicates > that few programs need this function. I haven't yet needed specifically qsort_r as well in portable code (and only once in non-portable private code), but I have mentioned it because it illustrates the fundamental problem with a missing context argument. I see the point that one shouldn't lightly double an API. Although I think that the current API is flawed with respect to a missing context parameter, we cannot change it either without breaking old code. One could use some macro-metaprogramming technique to get two versions for each module. Or one could add a global flag to the configuration (which ends in config.h) and which changes the behavior globally for the application (I am not sure whether this technique has been employed before). Marc