Functional programming throws away the "clarity of regular function calls" by abusing them or their syntax for control flow. It's an unreadable mess. Having control constructs be library functions seems to be an extension of this, making the situation much worse.
I write code to emulate the modern multi-GHz PC and other things running at about a GHz. It's timing sensitive, so the emulator needs to keep up, and we really want to emulate SMP on one core. My coworkers write code to treat a binary executable as a giant equation, solving it to find inputs which cause crashes. We pay lots of money for giant rooms full of computers running our code.
All programming languages are way too slow.
I'd switch to FORTRAN if it was 2x faster. I'm using C99 with lots of non-standard extensions and inline assembly. We use SSE intrinsics to vectorize things by hand.
Meanwhile, people like you are making my web browser too damn slow. It's 2016, and it feels like 1996. Other than a slight increase in pixels and always getting 24-bit color, there has been no improvement in speed despite the hardware being something like 1000 times faster. WTF. I paid good money for that hardware because I wanted things faster. I didn't buy that hardware to be wasted. Your code is not special. Each programmer tests his code in isolation, giving it the whole machine, but out in the wild it must share the machine with other code and/or with numerous instances of itself.
Sometimes gcc's optimizer will partially apply a function. I've seen the result via disassembler. This beats partially applying functions by hand. For example, the function may do different things if a certain parameter is NULL. The compiler makes a version of the function for when the parameter is NULL, and another for when it is not.
Passing a struct with a function pointer and argument seems a little annoying for a trivial situation, but it makes lots of sense when there are multiple functions and multiple arguments. For the trivial case, one would normally just pass the function pointer and argument separately.
I think I've written code that matches your "partially apply a function" idea pretty well, using macros. Like this:
There exist functions for reading/writing memory with names like read_mem_8 and read_mem_32, for several different sizes. I want to make wrapper functions called read8 and read32 and so on. The wrapper functions check for alignment, check a TLB, check for breakpoints, and then call the wrapped function or do the access directly. I make a macro that expands out to the function I want whenever I "call" the macro. No, I don't mean a regular function-like macro. Mine actually creates a real function. I invoke the macro itself at top level, outside of any function, right after creating the macro. I invoke it for each size that I want. Macro expansion generates a function that I can later call.
Invoking it looks like so:
define_read(8)
define_read(16)
define_read(32)
define_read(64)
define_write(8)
define_write(16)
define_write(32)
define_write(64)
Note the lack of a semicolon. These macros expand to actual functions that I can call. I could even take the address of the resulting functions if I wanted to, not that I do.
Invoking the result of the macro expansion looks like so:
write32(cpu,addr,val);
For bigger things, one would put the template-like version of the function in a .h file and then include it repeatedly, each time with different choices. Like so:
#define CHOSEN_BIT_WIDTH 32
#define CHOSEN_ENDIANNESS ENDIAN_BIG
#include "def_stuff.h"
#undef CHOSEN_BIT_WIDTH
#undef CHOSEN_ENDIANNESS
// ... and then again with different choices