03 Feb, 2009, Lobotomy wrote in the 1st comment:
Votes: 0
While I'm aware of the ability to similulate run-once function functionality in C using macros or othersuch, I'm curious if anyone here knows if C has an actual "once" option/attribute that is built-in or otherwise supported by gcc and the like; my searches through Google thusfar are not turning up any relevant information on the matter. :thinking:
03 Feb, 2009, David Haley wrote in the 2nd comment:
Votes: 0

Maybe some compiler somewhere has it, but that's not a very helpful statement nor is it likely to be a good thing to depend on.

It would help to search on the term 'memoization' (sic – no 'r'), though, which is the more common name for this kind of thing as far as I know.
03 Feb, 2009, Lobotomy wrote in the 3rd comment:
Votes: 0
I see.
03 Feb, 2009, David Haley wrote in the 4th comment:
Votes: 0
You're welcome :smile:

BTW, memoization isn't that hard to implement yourself if your function arguments are relatively straightforward – especially in C++ where you have std::map available.
03 Feb, 2009, Lobotomy wrote in the 5th comment:
Votes: 0
I…don't know if we're talking about the same thing here, now. When I say run-once functions, I mean the function is only allowed to run once; i.e, one call, subsequent calls raise an error or just don't run, whatever. This 'memoization' sounds a little more like the 'const' function attribute somewhat. :thinking:
03 Feb, 2009, Grimble wrote in the 6th comment:
Votes: 0
Use a static variable as a flag. For example…

void my_run_once_function()
static bool flag = false;

if (flag == false)
/* do something, just one time */

flag = true;
03 Feb, 2009, David Haley wrote in the 7th comment:
Votes: 0
Memoization has nothing to do with function constness [2], except in that a memoized function is necessarily const after the first invocation. [1]

A memoized function f can be defined as f : arg_1…arg_n –> result, such that the procedure 'f' is invoked exactly once per unique argument tuple arg_1…arg_n.

Grimble showed you how to implement a memoized function with no arguments and no return type. Here is an example in pseudo-code of a function that takes one argument and returns one argument.

f_memo_table = {}
function f(x)
if f_memo_table[x] then
return f_memo_table[x]
– do some computations
y = x + 1
f_memo_table[x] = y
return y

Clearly the "interesting" part of the function body will run exactly once per argument value. Grimble's will just as clearly run just once.

If you wanted it to throw an error, that's fine too, just change the memoization clause. E.g.,

if f_memo_table[x] then

In theory, at least – since in practice you can do whatever you want in the memoization function, upon having discovered that it's memoized already, the function isn't necessarily const.

By constness, I assume we are talking about freedom from side effects, since 'const' for functions floating in the void isn't something that's normally done. Const methods are indeed methods that will not modify the relevant object.
03 Feb, 2009, Lobotomy wrote in the 8th comment:
Votes: 0
I see. As for what Grimble said, that's essentially what I was alluding to earlier, although in my case I'm using a macro that runs an assert off the static boolean's value. I was simply looking for some kind of built-in method to use, such as a keyword into a function declaration. I.e, something like "once void function_example( stuff )". I can live without it, though. :sad:

As a side note, the information regarding memoization is rather interesting. I'll have to keep that optimization in mind and see what sort of functions I have that I can alter to make use of it. :thinking:
03 Feb, 2009, David Haley wrote in the 9th comment:
Votes: 0
Generally speaking – and without necessarily being exhaustive – memoization is useful when:

(1) it is less expensive to look up the argument tuple in the memoization table than it is to recompute the result
(2) you call the function with the same argument tuple repetitively
(3) the memoization table is not terribly large

I'd say that #2 is the most important: the more you call something with the same arguments, the more you want to memoize it, assuming #1 holds. (If it doesn't, memoization is a big waste of space and time.) #3 is important to keep in mind when thinking about space-time tradeoffs.
03 Feb, 2009, quixadhal wrote in the 10th comment:
Votes: 0
The technique is used quite a bit (especially in interpreted languages, like perl) for parsers, as you can have your initial setup loop through all recognized keywords to pre-evaluate them (which may load a bunch of other structures). Then when you're actually parsing your data stream, known identifiers don't have to do any work beyond a table lookup.