[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lies in education [was Re: The "loop and a half"]

On 12/10/2017 09:23, Christian Gollwitzer wrote:
> Am 12.10.17 um 01:15 schrieb Stefan Ram:
>> ?? Define a function ?g? with a parameter ?x? of type ?int?, so
>> ?? that this function ?g? returns a pointer to another function.
>> ?? This other function has a parameter of type ?char? and returns
>> ?? a double value.
> Ok
>> ?? /Without/ a typedef.
> And WHY would you do that? Typedefs do not cost money.

They cost extra effort in devising them, writing them, and having to 
trace them when someone else is reading the code.

> Try this:

> typedef double (*countdown_rate_func) (char letter);
> countdown_rate_func select_rate_func(int level);

> // I've substituted 'x' by 'level'
> // and 'g' by 'select_rate_func' for clarity

Those substitutions don't help, as I'm trying to see how well it matches 
the original spec. If I change them back (not easy to tell which bit is 

   typedef double (*F) (char);

   F g(int x);

No, sorry, it doesn't really cut it. It is still cryptic. It doesn't 
help that C doesn't use a keyword to introduce a function (like, say, 
'function'). You still need to know that double (*F) is a pointer to a 
function returning double, and that double *F is a function returning a 
pointer to a double.

It also introduces this arbitrary name 'F', which if you encounter it in 
source, means you know have to search for this typedef. (And the 
requirement was a definition not a declaration.)

> I claim that the above is quite clear, it declares a function in a 
> Countdown game engine, which, depending on the level, returns a 
> different function to rate the weight of the individual letters.

Renaming 'g' and 'x' to be more meaningful, and introducing a parameter 
name that is not needed, is a different subject. And actually I found 
your 'countdown_rate_func' and 'select_rate_func' names confusing (the 
two are actually of different rank, but both end in _func).

> Your exercise results in the line noise
>  ????double (*g(int x))(char)
> (thanks to Ben for doing the exercise), which is not extremely bad, but 
> still does tell nothing about the intent of that line.

Using any sane syntax for type (AND function) declarations, writing 
Stefan's function is straightforward. For example**:

     function g(int x) => ref function(char)real =
        return nil

Just transcribed exactly as written (I could have used 'x:int' maybe). 
If I translate this to C, then it gives me:

     static double (*g(int32 x)) (char) {
         return 0;

It's a piece of cake. It shows how important the right syntax can be; 
you write what you have to write, then get on with the rest of the 
coding. Oh, and it's also very easy to read.

It's a mystery to me actually; there is zero cost to devising, 
implementing and using the most helpful syntax, and actually there are 
real benefits. So why use something so bizarre?

(**This is my actual language but as someone guessed, this part is 
derived from Algol68.)