C3»Blog

Why does C3 use 'fn'?

Alongside the removal of goto, having adding an fn in front of function declarations seems superfluous and an arbitrary deviation from C.

Originally, C3 inherited this from C2, which at the time used func (it later simplified it to fn).

In C2 the keyword simplified grammar and made the code easier to search. In C3 however, it also made macro and function declarations symmetric:

macro int foo(int a) { ... }
fn int bar(int b) { ... }

Furthermore, it gives a simple and readable look for defining function types and lambdas:

def Foo = fn int();
Foo lambda = fn int() { return 1; };
Foo lambda_short = fn () => 1;

Because fn starts a declaration, it's easy to search for it using regex as well, or have some simple tool extracting function names.

So those are all straight up usability reasons for fn.

But there is one more:

// Which one is C3 code?

fn void my_function(int a)
{
    return a * a;
}

void my_function(int a)
{
    return a * a;
}

Yes, it being trivially simple to identify a C3 snippet really is an advantage as well as a disadvantage.

If you are converting C to C3, you might copy-paste the C code and piecemeal convert it. So how do you see what's C3 and what's C? Well the fn of course.

It might seem almost flippant to list this as something positive, but reinforcing a shift in interpretation can be surprisingly helpful.

Hi, i realy like the c3 approach of being a better c.

But 'fn' in front of function declarations IS A superfluous and an arbitrary deviation from C.

However 'fn' for defining function types and lambdas ARE OK.

// === OK FN ===

def Foo = fn int();

Foo lambda = fn int() { return 1; };

Foo lambda_short = fn () => 1;

// == NOT OK, TERRIBLE FN ==

fn void my_function(int a) { return a * a; }

Please remove the terrible one from c3! :-D

Error: This looks like the beginning of a function declaration but it's missing the initial fn. Did you forget it?

YES, I DID! :-D