О кешировании. Поговорим про устройство "слова".
Предыдущая серия была тут - http://programmingmindstream.blogspot.ru/2015/12/1147.html.
Там мы ввели понятия "слова", "переменной" и "константы", а также научились ими пользоваться.
Теперь поговорим на тему "а что же вообще говоря такое слово".
"Слово" или "элемент словаря" это вообще говоря - "словарная запись", которая представляется в словаре в виде "ключ-значение".
Т.е. слово:
В словаре будет представлено парой:
( A ACode )
Где:
A - имя слова.
ACode - код слова.
А точнее говоря - тройкой:
( : A ACode )
Где:
: - стереотип слова.
A - имя слова.
ACode - код слова.
Что такое стереотип слова?
Это скажем так "категория" к которой это "слово" относится.
Стереотип может определять различные ограничения на работу со словом.
Из разряда того, что например:
"константы" - умеют только вычислять значения.
"переменные" - умеют как отдавать значения, так и хранить их.
"слова" - умеют вычислять значения, а также могут содержать вложенные элементы.
Также стереотипы определяют наборы операций применимых к элементу словаря (об этом поговорим ещё позже).
Проиллюстрируем использование стереотипов примером:
Этот пример будет представлен в словаре так:
( : A ACode )
( VAR B {BValue} )
( CONST C 1 )
А пример:
Будет представлен в словаре так:
( : A ACode )
( VAR B {BValue} )
( CONST C 1 )
( CONST D ref C )
Обратите внимание, что элемент D не представлен значением "1", а ссылается на элемент C - "ref C".
Мы этот факт потом ещё обсудим.
А что же со вложенными словами?
Как они представляются в словаре?
Вот тут "оказывается", что слова представляются даже не тройкой, а четвёркой:
( Стереотип Имя_Слова Код_Слова Вложенный_Словарь ).
Проиллюстрируем примером.
Код:
Представляется как:
( : A ACode Dict( VAR X {XValue} ) )
Где Dict( ... ) - внутренний словарь слова A.
Ну и новый пример:
Будет представлен в словаре так:
( : A ACode Dict( VAR X {XValue} ) )
( VAR B {BValue} Dict( ) )
( CONST C 1 Dict( ) )
( CONST D ref C Dict( ) )
Тут возникает закономерный вопрос - "а раз словарь это ключ-значение, то нельзя ли получить поступ ко вложеным элементам слова?"
Ответ - "да можно, потому, что у нас присутствует полная рефлексия кода".
Как это сделать?
Для этого у нас есть три замечательных слова аксиоматики:
@ - получает адрес слова.
DO - выполняет слово по адресу (обратная к @).
%% - получает по адресу слова вложенный элемент по его имени.
Вот как определено слово %%:
Видим, что оно принимает два параметра - aWord и aName.
aWord - слово для которого мы ищем вложенный элемент.
aName - имя вложенного элемента.
И возвращает значение типа OBJECT - адрес найденного вложеного элемента, или nil, если такой элемент не найден.
Приведём пример использования:
Что получится?
В консоль напечатается целочисленное значение "2", которое возвращает слово X.
А что делать если искомого вложенного слова нет?
Ответ - проверить возвращаемое значение на nil.
Пример:
А можно ли обойтись без @ и DO?
Ответ - можно.
Для этого у нас есть слово - ::.
Вот как оно определено:
Пример использования:
Более того - при помощи :: можно не только читать, но и писать значения вложенных элементов (если они поддерживают запись).
На это указывает модификатор ^@ перед объявлением операции ::.
Он означает, что возвращается не значение, а ссылка.
Пример:
Теперь возникает закономерный вопрос - "а если мы можем получать внутренние элементы слов, то можем ли мы добавлять новые элементы?"
Ответ - "да можем".
Как?
Это мы рассмотрим в следующей статье.
Предыдущая серия была тут - http://programmingmindstream.blogspot.ru/2015/12/1147.html.
Там мы ввели понятия "слова", "переменной" и "константы", а также научились ими пользоваться.
Теперь поговорим на тему "а что же вообще говоря такое слово".
"Слово" или "элемент словаря" это вообще говоря - "словарная запись", которая представляется в словаре в виде "ключ-значение".
Т.е. слово:
: A ACode ; // A
В словаре будет представлено парой:
( A ACode )
Где:
A - имя слова.
ACode - код слова.
А точнее говоря - тройкой:
( : A ACode )
Где:
: - стереотип слова.
A - имя слова.
ACode - код слова.
Что такое стереотип слова?
Это скажем так "категория" к которой это "слово" относится.
Стереотип может определять различные ограничения на работу со словом.
Из разряда того, что например:
"константы" - умеют только вычислять значения.
"переменные" - умеют как отдавать значения, так и хранить их.
"слова" - умеют вычислять значения, а также могут содержать вложенные элементы.
Также стереотипы определяют наборы операций применимых к элементу словаря (об этом поговорим ещё позже).
Проиллюстрируем использование стереотипов примером:
: A ACode ; // A VAR B CONST C 1
Этот пример будет представлен в словаре так:
( : A ACode )
( VAR B {BValue} )
( CONST C 1 )
А пример:
: A ACode ; // A VAR B CONST C 1 CONST D C
Будет представлен в словаре так:
( : A ACode )
( VAR B {BValue} )
( CONST C 1 )
( CONST D ref C )
Обратите внимание, что элемент D не представлен значением "1", а ссылается на элемент C - "ref C".
Мы этот факт потом ещё обсудим.
А что же со вложенными словами?
Как они представляются в словаре?
Вот тут "оказывается", что слова представляются даже не тройкой, а четвёркой:
( Стереотип Имя_Слова Код_Слова Вложенный_Словарь ).
Проиллюстрируем примером.
Код:
: A VAR X ACode ; // A
Представляется как:
( : A ACode Dict( VAR X {XValue} ) )
Где Dict( ... ) - внутренний словарь слова A.
Ну и новый пример:
: A VAR X ACode ; // A VAR B CONST C 1 CONST D C
Будет представлен в словаре так:
( : A ACode Dict( VAR X {XValue} ) )
( VAR B {BValue} Dict( ) )
( CONST C 1 Dict( ) )
( CONST D ref C Dict( ) )
Тут возникает закономерный вопрос - "а раз словарь это ключ-значение, то нельзя ли получить поступ ко вложеным элементам слова?"
Ответ - "да можно, потому, что у нас присутствует полная рефлексия кода".
Как это сделать?
Для этого у нас есть три замечательных слова аксиоматики:
@ - получает адрес слова.
DO - выполняет слово по адресу (обратная к @).
%% - получает по адресу слова вложенный элемент по его имени.
Вот как определено слово %%:
OBJECT operator %% OBJECT IN aWord ^ IN aName OBJECT VAR l_Member aName DO aWord pop:Word:FindMember >>> l_Member if ( l_Member pop:object:IsNil ) then ( Result := nil ) else ( Result := ( l_Member pop:KeyWord:Word ) ) ; // %%
Видим, что оно принимает два параметра - aWord и aName.
aWord - слово для которого мы ищем вложенный элемент.
aName - имя вложенного элемента.
И возвращает значение типа OBJECT - адрес найденного вложеного элемента, или nil, если такой элемент не найден.
Приведём пример использования:
: A : X 2 ; // X 1 ; // A @ A // - берём адрес слова A %% // - операция %% 'X' // - имя искомого слова X DO // - выполняем слово, которое нашлось Print // - печатаем значение
Что получится?
В консоль напечатается целочисленное значение "2", которое возвращает слово X.
А что делать если искомого вложенного слова нет?
Ответ - проверить возвращаемое значение на nil.
Пример:
: A : X 2 ; // X 1 ; // A VAR l_ElementAddr // - переменная для сохранения адреса элемента @ A %% 'X' >>> l_ElementAddr // - получаем адрес элемента X if NOT ( l_ElementAddr IsNil ) then // - проверяем его begin l_ElementAddr DO // - напечатается 2 end @ A %% 'Y' >>> l_ElementAddr // - получаем адрес элемента Y if NOT ( l_ElementAddr IsNil ) then // - проверяем его begin l_ElementAddr DO // - ничего, не напечатается, // т.к. сюда не попадём, // т.к. у элемента A нет элемента Y end
А можно ли обойтись без @ и DO?
Ответ - можно.
Для этого у нас есть слово - ::.
Вот как оно определено:
^@ operator :: ^@ IN aSelf ^L IN aName OBJECT VAR l_Self aSelf |^@ >>> l_Self STRING VAR l_Name aName |N >>> l_Name OBJECT VAR l_Res l_Self %% l_Name >>> l_Res ASSURE NOT ( l_Res pop:object:IsNil ) [ 'Не найдено поле: ' l_Self LIST %P Reverted ==> ( |N '::' ) l_Self |N '::' l_Name ] l_Res >>> Result ; // ::
Пример использования:
: A : X 2 ; // X 1 ; // A A :: X Print // - напечатает значение "2", которое возвращает X A :: Y Print // - упадёт с Run-Time ошибкой, что "поле Y не найдено"
Более того - при помощи :: можно не только читать, но и писать значения вложенных элементов (если они поддерживают запись).
На это указывает модификатор ^@ перед объявлением операции ::.
Он означает, что возвращается не значение, а ссылка.
Пример:
: A VAR X ; // A A :: X := 2 // - присваиваем полю X значение "2" A :: X Print // - печатаем это значение
Теперь возникает закономерный вопрос - "а если мы можем получать внутренние элементы слов, то можем ли мы добавлять новые элементы?"
Ответ - "да можем".
Как?
Это мы рассмотрим в следующей статье.
Комментариев нет:
Отправить комментарий