Инструменты пользователя

Инструменты сайта


bb:redbook:213

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Предыдущая версия справа и слева Предыдущая версия
Следующая версия
Предыдущая версия
bb:redbook:213 [2016/09/08 09:37]
prospero78 [5. Заключение]
bb:redbook:213 [2020/10/29 07:08] (текущий)
Строка 2: Строка 2:
  
 ==== 1. Оператор выбора CASE ==== ==== 1. Оператор выбора CASE ====
-Компонетный Паскаль предлагает инструкции выбора IF ELSIF ELSE. Их можно комбинировать в произволной последовательности и глубине. Но довольно часто случается, что выбор происходит больше, чем из одной-двух альтернатив. Бородатые компьютерщики помнят, что в начальных меню ДОСа довольно часто, для выбора пункта меню приходилось выбирать номер пункта и вводить его через клавиатуру. Так происходило интерактивное взаимодействие в эпоху чёрных экранов. Если посмотреть на исходники многих современных программ, выбор "что надо сделатьдо сих пор построен именно так (хотя эта логика скрыта "плюшками""приблудамии "контроламиинтерфейса графического пользователя).+Компонентный Паскаль предлагает инструкции выбора ''IF ELSIF ELSE''. Их можно комбинировать в произвольной последовательности и глубине. Но довольно часто случается, что выбор происходит больше, чем из одной-двух альтернатив. Бородатые компьютерщики помнят, что в начальных меню ДОСа довольно часто, для выбора пункта меню приходилось выбирать номер пункта и вводить его через клавиатуру. Так происходило интерактивное взаимодействие в эпоху чёрных экранов. Если посмотреть на исходники многих современных программ, выбор //что надо сделать// до сих пор построен именно так (хотя эта логика скрыта //плюшками////приблудами// и //контролами// интерфейса графического пользователя).
  
-Так когда же нужно применять оператор выбора CASE? Должно быть выполнено два условия:+Так когда же нужно применять оператор выбора ''CASE''? Должно быть выполнено два условия:
  
   - Выбор надлежит сделать из более чем двух величин.   - Выбор надлежит сделать из более чем двух величин.
   - Выбираемые величины должны быть однотипными -- целыми или литерными.   - Выбираемые величины должны быть однотипными -- целыми или литерными.
  
-Как использовать оператор CASE представлено ниже:+Как использовать оператор ''CASE'' представлено ниже: 
 +<code oberon2> 
 +MODULE Test_case; 
 + 
 + IMPORT 
 + Log; 
 + 
 + PROCEDURE SelectV (v: INTEGER); 
 + BEGIN 
 + Log.String("v:="); Log.Int(v); Log.Ln; 
 + CASE v OF 
 + 1..10: Log.String("Малое число"); Log.Ln; 
 + | 11..100: Log.String("Среднее число"); Log.Ln; 
 + | 101..1000: Log.String("Ого! Большое число!"); Log.Ln; 
 + ELSE 
 + Log.String("Нет. Это что-то не то..."); Log.Ln; 
 + END; 
 + 
 + END SelectV; 
 + 
 + PROCEDURE Start*; 
 + VAR 
 + v: INTEGER; 
 + BEGIN 
 + v := 6; 
 + SelectV(v); 
 + v := 12; 
 + SelectV(v); 
 + v := 102; 
 + SelectV(v); 
 + v := - 1; 
 + SelectV(v); 
 + END Start; 
 + 
 +END Test_case. 
 +</code> 
 +Вывод: 
 +<code> 
 +компилируется "Test_case" 252 0 
 +старый модуль Test_case выгружен 
 +v := 6 
 +Малое число 
 +v := 12 
 +Среднее число 
 +v := 102 
 +Ого! Большое число! 
 +v := - 1 
 +Нет. Это что - то не то... 
 +</code>
   
-Как видно из текста модуля, количество веток с ELSE было бы драматически большим, пришлось бы написать больше кода, а значит риск совершения ошибки увеличивается. Кроме того, более компактная форма записи, позволяет сократить занимаемое место на экране, что положительно сказывается на понимании текста программы. [↑]+Как видно из текста модуля, количество веток с ''ELSE'' было бы драматически большим, пришлось бы написать больше кода, а значит риск совершения ошибки увеличивается. Кроме того, более компактная форма записи, позволяет сократить занимаемое место на экране, что положительно сказывается на понимании текста программы.
   
   
 ==== 2. Ключевые слова модуля ====  ==== 2. Ключевые слова модуля ==== 
 Таких слов на данный момент рассмотрено три: Таких слов на данный момент рассмотрено три:
-  - MODULE [NameModule];  -- обязательное ключевое слово с именем модуля. По другому компилятор никак не сможет определить к чему относится программный текст. +  - ''MODULE'' [NameModule];  -- обязательное ключевое слово с именем модуля. По другому компилятор никак не сможет определить к чему относится программный текст. 
-  - END [NameModule]. -- обязательное ключевое слово с именем модуля. По другому компилятор никак не сможет определить, где заканчивается программный код. Нельзя забывать, что за концом программного текста ещё могут быть различные элементы, как-то: коммандер (а то и не один), данные для ввода, данные для компиляции, заметки типа TODO или краткие примеры правильного использования. Кроме того, можно вставить ссылки на документацию по модулю или смежные темы. +  - ''END'' [NameModule]. -- обязательное ключевое слово с именем модуля. По другому компилятор никак не сможет определить, где заканчивается программный код. Нельзя забывать, что за концом программного текста ещё могут быть различные элементы, как-то: коммандер (а то и не один), данные для ввода, данные для компиляции, заметки типа **TODO** или краткие примеры правильного использования. Кроме того, можно вставить ссылки на документацию по модулю или смежные темы. 
-  - BEGIN -- необязательное ключевое слово уровня модуля. Обычно, код размещённый после него -- исполняется для служебных целей во время загрузки самого модуля. По возможности, не стоит использовать это логическое пространство для кода. С высокой вероятностью, это будет плохим решением. +  - ''BEGIN'' -- необязательное ключевое слово уровня модуля. Обычно, код размещённый после него -- исполняется для служебных целей во время загрузки самого модуля. По возможности, не стоит использовать это логическое пространство для кода. С высокой вероятностью, это будет плохим решением. 
-  - CLOSE -- необязательное ключевое слово уровня модуля. Обычно, код размещённый после него -- исполняется для служебных целей во время выгрузки самого модуля. Эта возможность используется ещё реже, чем BEGIN, так что с ещё большей вероятностью использование этой секции будет ещё более плохим решением.+  - ''CLOSE'' -- необязательное ключевое слово уровня модуля. Обычно, код размещённый после него -- исполняется для служебных целей во время выгрузки самого модуля. Эта возможность используется ещё реже, чем ''BEGIN'', так что с ещё большей вероятностью использование этой секции будет ещё более плохим решением.
  
-Читатели знакомые, например, с python, обратят своё внимание, что это очень похоже на специальные методы классов __init__ и __del__. И такое сходство будет не случайно. Вспоминаем, что основная единица компиляции в КП -- модуль! И понятие модуля органически совмещается с понятием класса. [↑]+Читатели знакомые, например, с **python**, обратят своё внимание, что это очень похоже на специальные методы классов ''__init__'' и ''__del__''. И такое сходство будет не случайно. Вспоминаем, что основная единица компиляции в КП -- //модуль//! И понятие //модуля// органически совмещается с понятием //класса//. И всё же, надо помнить, что ''BEGIN'' и ''CLOSE'' относятся к модулю, а не классу (которых в **python** в одном модуле может быть несколько, хотя сами же питонёры к такой практике относятся не очень хорошо).
   
   
-=== 3. Арифмитические и логические операции === +==== 3. Арифметические и логические операции ==== 
-Здесь будут рассмотрены только обойдённые внимание операции. +Здесь будут рассмотрены только обойдённые вниманием операции. 
-  - MOD -- бывает весьма полезная операция для поиска остатка при целочисленном делении. Можно вычислить остаток и через программное решение, но оно гарантированно будет более медленней. Пример: 5 MOD 3 = 2. +  - ''MOD'' -- бывает весьма полезная операция для поиска остатка при целочисленном делении. Можно вычислить остаток и через программное решение, но оно гарантированно будет более медленней. Пример: ''5 MOD 3 = 2''
-  - DIV -- также весьма полезная операция для целочисленного деления (т.е. когда оба операнда имеют целочисленный тип, и результат имеет его же). Также работает заметно быстрее, чем операции над вещественными числами. Пример: 5 DIV 3 =  1. Разумеется, точность страдает, но бывает это приемлемо. +  - ''DIV'' -- также весьма полезная операция для целочисленного деления (т. е. когда оба операнда имеют целочисленный тип, и результат имеет его же). Также работает заметно быстрее, чем операции над вещественными числами. Пример: ''5 DIV 3 =  1''. Разумеется, точность страдает, но бывает это приемлемо. 
-  - ~[число] -- "выворачиваетчисло. Инвертирует все биты.  +  - ''~[число]'' -- //выворачивает// число. Инвертирует все биты.  
-  - OR -- логическое сложение чисел, бывает полезным, например, при наложении изображений. Пример: 3 OR 2 = 3. +  - ''OR'' -- логическое сложение чисел, бывает полезным, например, при наложении изображений. Пример: ''3 OR 2 = 3''
-  - & -- логическое умножение (читается "амперсанд"). Бывает полезным при, например: шифровании, обработки изображений. Пример: 5 & 3 = 1. +  - ''&'' -- логическое умножение (читается "амперсанд"). Бывает полезным при, например: шифровании, обработки изображений. Пример: ''5 & 3 = 1''
-  - IN -- принадлежность к множеству. Не путать с параметрами на вход в процедурах! Пример: 6 in a. Где а: ARRAY 1000 OF BYTE (или ещё чего-нибудь). Если значение 6 содержаится в массиве а, то результатом этого выражения будет TRUE, в противном случае FALSE. +  - ''IN'' -- принадлежность к множеству. Не путать с параметрами на вход в процедурах! Пример: ''6 in a''. Где ''а: ARRAY 1000 OF BYTE'' (или ещё чего-нибудь). Если значение 6 содержится в массиве ''а'', то результатом этого выражения будет ''TRUE'', в противном случае ''FALSE''
-  - IS -- принадлежность к типу. Бывает полезным узнать во время выполнения программы к какому типу относится переменная (например, в качестве охраны условия, или значения выражения в ASSERT). Пример: ASSERT (counter IS INTEGER). Аналогично с предыдущим ключевым словом результатом вычисления является TRUE или FALSE. Оператор IS вводит в Компонетный Паскаль возможности интроспекции (исследование "системы во внутрь"). [↑]+  - ''IS'' -- принадлежность к типу. Бывает полезным узнать во время выполнения программы к какому типу относится переменная. Используется вместо с оператором выбора типа ''WITH'' . Аналогично с предыдущим ключевым словом результатом вычисления является ''TRUE'' или ''FALSE''. Оператор ''IS'' вводит в **Компонентный Паскаль** возможности интроспекции (исследование "системы во внутрь"). 
 +  - ''ASSERT'' -- оператор охраны. Вызывает системное исключение, если выражение  скобках не соответствует истине. Например, ''ASSERT( (10<i) & (i<20), 20)''. Системное исключение возникнет тогда, когда ''i'' будет меньше или равно 10 и больше или равно 20.
   
   
-=== 4. Оператор WITH ===+==== 4. Оператор WITH ====
 Этот оператор занимает промежуточное положение между оператором контекста, оператором приндлежности к типу и оператором множественного выбора. В динамических средах бывает сложно предугадать тип "подсовываемой" переменной. И в зависимости от типа, нужно выполнять различные действия. Этот оператор занимает промежуточное положение между оператором контекста, оператором приндлежности к типу и оператором множественного выбора. В динамических средах бывает сложно предугадать тип "подсовываемой" переменной. И в зависимости от типа, нужно выполнять различные действия.
  
 Например:  Например: 
 +<code oberon2>
 +MODULE Test_case;
 +
 + IMPORT
 + Log;
 +
 + TYPE
 + tRecord = EXTENSIBLE RECORD
 + x: INTEGER;
 + y: INTEGER;
 + END;
 +
 + tRecord1 = RECORD (tRecord)
 + z: INTEGER;
 + END;
 +
 + PROCEDURE SelectV (VAR v: tRecord);
 + BEGIN
 + WITH
 + v: tRecord1 DO
 + Log.String("Это тип tRecord1");
 + Log.Ln;
 + | v: tRecord DO
 + Log.String("Это тип tRecord");
 + Log.Ln;
 + ELSE
 + Log.String("Нет. Это что-то не то..."); Log.Ln;
 + END;
 +
 + END SelectV;
 +
 + PROCEDURE Start*;
 + VAR
 + v: POINTER TO tRecord;
 + v1: POINTER TO tRecord1;
 +
 + BEGIN
 + NEW(v);
 + NEW(v1);
 + v.x := 6;
 + SelectV(v);
 + v1.z := 3;
 + SelectV(v1);
 + END Start;
 +
 +END Test_case.
 +</code>
 +Вывод:
 +<code>
 +компилируется "Test_case" 176 0
 +старый модуль Test_case выгружен
 +Это тип tRecord
 +Это тип tRecord1
 +</code>
   
   
-В приведённом примере создаётся тип tRecord и наследующий его tRecord1. Процедура SelectV принимает только тип tRecord, и, теоретически, компилятор должен был грязно выругаться при попытке скомплировать этот пример. Ведь в процедурое Start видна попытка скормить для SelectV переменную типа tRecord1 (а это уже другой тип). Но компилятор соглашается!!!+В приведённом примере создаётся тип ''tRecord'' и наследующий его ''tRecord1''. Процедура ''SelectV'' принимает только тип ''tRecord'', и, теоретически, компилятор должен был грязно выругаться при попытке скомпилировать этот пример. Ведь в процедуре ''Start'' видна попытка скормить для ''SelectV'' переменную типа ''tRecord1'' (а это уже другой тип). Но компилятор соглашается!!!
  
-После этого в процедуре SelectV использована небольшая хитрость. Так как одна из переменных имеет тип tRecord1, то при первом вызове эта ветка будет пропущена (и это правильно, так как тип переменной -- tRecord). А во втором случае выполнение пойдёт именно по первой ветке (и это тоже правильно, так как второй тип -- tRecord1 является расширением tRecord). После выполнения одной из веток -- другие ветки выполняться не будут.+После этого в процедуре ''SelectV'' использована небольшая хитрость. Так как одна из переменных имеет тип ''tRecord1'', то при первом вызове эта ветка будет пропущена (и это правильно, так как тип переменной -- ''tRecord''). А во втором случае выполнение пойдёт именно по первой ветке (и это тоже правильно, так как второй тип -- ''tRecord1'' является расширением ''tRecord''). После выполнения одной из веток -- другие ветки выполняться не будут.
  
-В тоже время, необходимо обратить внимание, что если в коде попытаться передать переменную типа INTEGER (или вообще любую, не наследующую и не являющуся типом tRecord) -- компилятор просто откажется компилировать такой модуль. [↑]+В тоже время, необходимо обратить внимание, что если в коде попытаться передать переменную типа ''INTEGER'' (или вообще любую, не наследующую и не являющуюся типом ''tRecord'') -- компилятор просто откажется компилировать такой модуль.
   
   
 ==== 5. Заключение ==== ==== 5. Заключение ====
-Приведённые особенности Компонетного Паскаля надо знать. Можно посоприть с тем, что, например CASE может и излишняя семантическая контсрукция в языке, но опытные программисты на практическом примере покажут вам преимущества того или иного способа. Важно иметь практику, и понимание, что для чего предназначено.+Приведённые особенности **Компонентного Паскаля** надо знать. Можно поспорить с тем, что, например ''CASE'' может и излишняя семантическая конструкция в языке, но опытные программисты на практическом примере покажут вам преимущества того или иного способа. Важно иметь практику, и понимание, что для чего предназначено.
  
-В качестве самостоятельного задания, которое потребует почитать документацию, рекомендуется составить две программы с помощью IF THEN ELSE  и CASE, и сравнить быстродействие на 10 ветках исполнения (подсказка: Time).+В качестве самостоятельного задания, которое //потребует почитать// документацию, рекомендуется составить две программы с помощью ''IF THEN ELSE''  и ''CASE'', и сравнить быстродействие на 10 ветках исполнения ((подсказка: Time)).
   
bb/redbook/213.1473316647.txt.gz · Последнее изменение: 2020/10/29 07:08 (внешнее изменение)