From Esolang
Jump to navigation Jump to search


What about inconsistent programs like the following? --Int-e (talk) 12:42, 28 February 2020 (UTC)

int *x = g;

int f(int n) {
    return x[n] == 0 ? 1 : 0;

int g(int n) {
    return f(n);
From the article page itself (paragraph Overview, section Functions, last sentence): "Therefore, global variables, nested functions and side-effects are forbidden." In particular, your example throws a syntax error. Regarding logical consistency: except from being uncomputable on a Turing machine, the language does not trivially seem to be paradoxical. You may try to refactor your example into something like
int f(){
  int* x = g;
  return x[0];

int g(int n){
  return f() + 1;
but it is still not paradoxical. It is simply an infinite loop, equivalent to
int x = 0;
while(x != x + 1) x++;
--Hakerh400 (talk) 13:48, 28 February 2020 (UTC)
If you resolve inconsistencies through non-termination, then you should specify this in the semantics. Most notably, any value can embed non-termination, except possibly for `int` values (where you can fail to terminate rather than assigning a non-terminating value). This affects equality testing... for `int *f; int *g`, if `f` or `g` fail to terminate on some inputs, how is `f = g` defined? Or, one level higher up, if you have `int **f; int **g;`, does testing `f = g` check arguments that are not total functions? --Int-e (talk) 14:19, 28 February 2020 (UTC)
Regarding the restriction on nested functions and global variables, why don't you state so up front? To me (skimming the article looking for the important bits), the example at Int**#Functions indicated that there are global variables; I didn't expect to find a restriction on syntax at that point in the description. --Int-e (talk) 14:25, 28 February 2020 (UTC)
Let's say that behavior in any disputable situation is implementation-dependent. --Hakerh400 (talk) 17:13, 28 February 2020 (UTC)
Actually, after a bit of thinking, I believe this can be defined in a better way. If we work only with int types, then it can be simulated using a regular Turing machine and it may or may not terminate. However, when we introduce int* types, the problematic part is the conversion from function int(int) to int* (which can be done either by assigning a function name to a variable of type int*, or returning a function name from a function that is declared to return a value of type int*). We can resolve any inconsistency by defining the conversion in the following way: when for example we have int f(int n){...} and we assign it to int* x = f;, then spawn infinitely many machines at once and let each of them calculate f for specific integer value n. Then wait until each of the spawned machines halts and then construct x based of the outputs of each machine. Initialization of x terminates if and only if each call to f terminates in finite time. Similar can be applied to int** types and higher. Regarding your question "does testing f = g check arguments that are not total functions? - the answer is no, because we cannot even have a variable that is not fully initialized. And that is also the difference between int(int) and int* - int(int) is a function that 1) cannot be modified and 2) may or may not terminate, while int* can be modified and is always a fully initialized value. Also, int(int) can be parametrized with other arguments, while int* is a concrete value. Back to your code example (and my example without using globals) - initialization of x will not terminate because some of the spawned machines (that are intended to call f with all possible arguments) do not terminate. --Hakerh400 (talk) 08:29, 4 March 2020 (UTC)