В Active Oberon в процедурах-функциях доступна локальная переменная RESULT
. Она представляет собой ссылку на переменную, в которую возвращают значение. Это сделано для возможности экономить ресурсы при возврате структур (массивов, записей и указателей на них), но такое решение хранит в себе подвох.
Если актуальный параметр совпадает с переменной, принимающей значение, есть риск пересечения ссылок, что может привести к ошибочному результату[0].
MODULE Reverse; IMPORT Out;
TYPE Arr = ARRAY 3 OF INTEGER;
PROCEDURE DoSurprize*(CONST a: Arr): Arr;
VAR i: INTEGER;
BEGIN
FOR i := 0 TO LEN(a) - 1 DO
RESULT[i] := a[LEN(a) - i - 1]
END;
RETURN RESULT
END DoSurprize;
PROCEDURE Do* (CONST a: Arr): Arr;
VAR i: INTEGER; RESUIT: Arr;
BEGIN
FOR i := 0 TO LEN(a) - 1 DO
RESUIT[i] := a[LEN(a) - i - 1]
END;
RETURN RESUIT
END Do;
PROCEDURE Test*;
PROCEDURE Go(reverse: PROCEDURE(CONST a: Arr): Arr);
VAR i: INTEGER; a, b: Arr;
BEGIN
FOR i := 0 TO LEN(a) - 1 DO a[i] := i END;
b := reverse(a);
FOR i := 0 TO LEN(b) - 1 DO Out.Int(b[i], 4) END; Out.Ln;
b := reverse(b);
FOR i := 0 TO LEN(b) - 1 DO Out.Int(b[i], 4) END; Out.Ln; Out.Ln
END Go;
BEGIN
Go(Do);
Go(DoSurprize)
END Test;
END Reverse.
Что приводит к результату:
2 1 0 0 1 2 2 1 0 0 1 0
Можно делать и совсем странные вещи. Например, использовать выходную переменную в качестве входного значения и писать функции без явных параметров.
MODULE Reverse2; IMPORT Out;
TYPE Arr = ARRAY 4 OF INTEGER;
PROCEDURE Do*(): Arr;
VAR i, t: INTEGER;
BEGIN
FOR i := LEN(RESULT) DIV 2 TO 1 BY -1 DO
t := RESULT[i - 1];
RESULT[i - 1] := RESULT[LEN(RESULT) - i];
RESULT[LEN(RESULT) - i] := t
END;
RETURN RESULT
END Do;
PROCEDURE Test*; VAR i: INTEGER; a: Arr;
BEGIN
a := INTEGER([0, 1, 2, 3]);
a := Do();
FOR i := 0 TO LEN(a) - 1 DO Out.Int(a[i], 4) END; Out.Ln
END Test;
END Reverse2.
3 2 1 0
Комментариев нет:
Отправить комментарий