Предыдущая серия была тут - 
#1163. :, PROCEDURE, FUNCTION. Параметры справа и слева.Часть 1.
Там мы рассмотрели ключевые слова 
:, 
;, 
FUNCTION, 
PROCEDURE.
А также "параметры слева".
Рассмотрим теперь "параметры справа".
Пусть у нас есть пример с "параметрами слева":
INTEGER FUNCTION Plus
 INTEGER IN A
 INTEGER IN B
 A B + >>> Result // - складываем A и B и помещаем в Result
; // Plus
1 2 Plus . // - вызываем нашу функцию и печатаем результат
Тут мы имеет "типичную" 
ОПЗ.
А что делать, если мы хотим пользоваться 
инфиксной нотацией?
Вот тут нам помогут 
параметры справа.
Перепишем наш пример с использованием 
параметров справа:
INTEGER FUNCTION Plus
 INTEGER IN A // - параметр слева
 ^ IN B // - параметр СПРАВА передаётся по ССЫЛКЕ, а не по ЗНАЧЕНИЮ. 
        //   Его надо разыменовывать.
 A // - значение параметра A
 B DO // - разыменовываем значение B. Т.е. зовём метод DO на том слове на которое указывает B
 + >>> Result // - складываем A и B и помещаем в Result
; // Plus
1 Plus 2 . // - вызываем нашу функцию ИНФИКСНО и печатаем результат
Подчеркну, что 
параметры справа передаются 
по ссылке.
Также можно написать:
1 Plus ( 2 Plus ( 3 Plus 4 ) ) .
Скобки пока обязательны.
Как обойтись без скобок - напишу отдельно.
Также наш пример можно переписать так:
INTEGER FUNCTION Plus
 INTEGER IN A // - параметр слева
 ^ IN B // - параметр СПРАВА передаётся по ССЫЛКЕ, а не по ЗНАЧЕНИЮ. 
        //   Его надо разыменовывать.
 A // - значение параметра A
 B |^ // - разыменовываем значение B. Т.е. зовём метод |^ на том слове на которое указывает B
 + >>> Result // - складываем A и B и помещаем в Result
; // Plus
1 Plus 2 . // - вызываем нашу функцию ИНФИКСНО и печатаем результат
Тут используется |^ вместо DO.
Они вообще говоря равноценны.
Про 
отличия я напишу несколько позже.
Метод |^ в аксиоматике определяется так:
: |^
  ^@ IN aRef
  
 %SUMMARY 'Разыменовывает параметр слева' ;
 aRef pop:Word:GetRef DO
; // |^
Детали реализации |^ я также опишу позже.
Но пока отмечу, что |^ использует DO. Т.е. |^ является производным от DO.
Пойдём далее.
Зачем параметры справа передаются по ссылке,а не по значению?
Тому есть много причин.
В частности - "
ленивые вычисления".
Рассмотрим реализацию булевских операций AND и OR.
Вот она:
BOOLEAN operator AND 
  BOOLEAN IN aFirst
  ^ IN aSecond
 %SUMMARY 'Двусторонний, а не обратный польский &&' ;
 if aFirst then
  (
   if ( aSecond DO ) then
    ( true >>> Result )
   else
    ( false >>> Result )
   )
 else
  ( false >>> Result )
; // AND
BOOLEAN operator OR 
  BOOLEAN IN aFirst
  ^ IN aSecond
 // Двусторонний, а не обратный польский ||
 if aFirst then
  ( Result := true )
 else
  if ( aSecond DO ) then
   ( Result := true )
  else
   ( Result := false )
; // OR
Тут видно, что параметр 
aSecond будет вычисляться ТОЛЬКО если он нужен для вычисления всего выражения.
Т.е. если по параметру 
aFirst - результат выражения будет 
ещё неясен.
Слово operator является аналогом слов : и FUNCTION. ОН лишь подчёркивает "операторную сущность" определяемых слов.
В частности - операторам можно задавать "
приоритет выполнения" как например в 
Prolog.
Чтобы например избавиться от скобок в примере со словом Plus выше.
Но об этом расскажу отдельно.
Но пока будем считать, что operator определён как:
WordAlias operator :
WordAlias OPERATOR :
И что мы получаем с 
ленивыми вычислениями?
Если написать без ленивых вычислений:
if ( ( anObject <> nil ) ( anObject .SomeMethod ) && ) then
То получим Access Violation.
А с ленивыми вычислениями:
if ( ( anObject <> nil ) AND ( anObject .SomeMethod ) ) then
Access Violation - не будет.
Надеюсь - понятно почему.
Операция 
<> кстати тоже определена в базовой аксиоматике при помощи 
правых и 
левых параметров. И через операцию =.
Вот так:
BOOLEAN operator <>
  IN aLeft
  ^ IN aRight
 %SUMMARY 'Правосторонний, а не обратный польский !=' ;
 Result := ( aLeft = ( aRight DO ) ! )
; //<>
Комментировать не буду. Отмечу лишь, что операция 
! - это 
постфиксное отрицание.
Пойдём далее.
Тот факт, что передаётся ссылка на слово, а не значение означает то, что если в качестве слова падали переменную, то мы можем писать в неё.
Реализуем например методы инкремента и декремента.
Так как они описаны в аксиоматике:
VOID operator DEC
  ^ IN aWhatToDecrement
 aWhatToDecrement DO // - разыменовываем переменную aWhatToDecrement
 1 - // - вычитаем единицу
 >>>^ aWhatToDecrement // - записываем значение туда куда указывает aWhatToDecrement
; // DEC
VOID operator INC
  ^ IN aWhatToIncrement
 aWhatToIncrement DO // - разыменовываем переменную aWhatToDecrement
 1 + // - прибавляем единицу
 >>>^ aWhatToIncrement // - записываем значение туда куда указывает aWhatToIncrement
; // INC
И вызов:
INTEGER VAR A // - определяем целочисленную переменную A
0 >>> A // - инициализируем её нулём
A . // - печатаем
INC A // - увеличиваем A на единицу
A . // - печатаем
DEC A // - уменьшаем A на единицу
A . // - печатаем
Понятное дело, что если мы напишем Inc 1, то мы получим ошибку если не 
компиляции, то времени исполнения.
Ну и предположим нам надо описать методы IncBy и DecBy.
Вот они:
VOID operator DecBy
  ^ IN aWhatToDecrement
  ^ IN aDelta
 aWhatToDecrement DO // - разыменовываем переменную aWhatToDecrement
 aDelta DO // - разыменовываем переменную aDelta
 - // - вычитаем
 >>>^ aWhatToDecrement // - записываем значение туда куда указывает aWhatToDecrement
; // DecBy
VOID operator IncBy
  ^ IN aWhatToIncrement
  ^ IN aDelta
 aWhatToIncrement DO // - разыменовываем переменную aWhatToDecrement
 aDelta DO // - разыменовываем переменную aDelta
 + // - прибавляем
 >>>^ aWhatToIncrement // - записываем значение туда куда указывает aWhatToIncrement
; // IncBy
И вызов:
INTEGER VAR A // - определяем целочисленную переменную A
0 >>> A // - инициализируем её нулём
A . // - печатаем
IncBy A 2 // - увеличиваем A на 2
A . // - печатаем
DecBy A 2 // - уменьшаем A на 2
A . // - печатаем
Пойдём далее. 
Параметры справа также удобно использовать для обращения к 
лямбда-выражениям.
Приведу пример:
: Iteration
  ^ IN aLambda
 0 // - начальное значение
 1 aLambda DO
 2 aLambda DO
 3 aLambda DO
 4 aLambda DO
 5 aLambda DO
 6 aLambda DO
 7 aLambda DO
 8 aLambda DO
 9 aLambda DO
 10 aLambda DO
; // Iteration
// Вызов:
Iteration ( IN A IN B A B + ) . // - просуммирует числа от 0 до 10 и напечатает сумму
// Или короче:
Iteration + . // - просуммирует числа от 0 до 10 и напечатает сумму
Можно вынести начальное значение за скобки:
: Iteration
  ^ IN aLambda
 1 aLambda DO
 2 aLambda DO
 3 aLambda DO
 4 aLambda DO
 5 aLambda DO
 6 aLambda DO
 7 aLambda DO
 8 aLambda DO
 9 aLambda DO
 10 aLambda DO
; // Iteration
// Вызов:
0 Iteration ( IN A IN B A B + ) . // - просуммирует числа от 0 до 10 и напечатает сумму
// Или короче:
0 Iteration + . // - просуммирует числа от 0 до 10 и напечатает сумму
1 Iteration * . // - перемножит числа от 1 до 10 и напечатает произведение
Также можно использовать 
массивы и 
итерацию по ним:
: Iteration
  ^ IN aLambda
 [ 1 2 3 4 5 6 7 8 9 10 ] .for> ( aLambda DO )
; // Iteration
// Вызов:
0 Iteration ( IN A IN B A B + ) . // - просуммирует числа от 0 до 10 и напечатает сумму
// Или короче:
0 Iteration + . // - просуммирует числа от 0 до 10 и напечатает сумму
1 Iteration * . // - перемножит числа от 1 до 10 и напечатает произведение
Подведём итоги.
Мы разобрали 
параметры справа. Их 
разыменование.
Также мы разобрали запись значений в те переменные на которые указывают параметры справа.
Также мы рассмотрели как параметры справа могут использоваться для лямбда-выражений.
Также мы немного коснулись массивов и итерации по ним.
В следующей статье мы разберём 
параметры слева передаваемые 
по ссылке и рассмотрим как например реализовать операции такие как 
+= -= и т.п.
Надеюсь, что данная статья была вам полезна.