перехода, связанные с им проблемы и способы их решения в современных




ЯП.

IF

С,C++:

if (B) then

Operator1

else

Operator2

АДА:

if B then

S1;S2;S3;...

End if

Оберон:

IF B THEN

S1;S2;S3;S4...

ELSE

S1;S2;S3;S4...

END

Оператор выбора - дискретный случай.

в Паскале:

Case Expr of

список вариантов, Вариант имеет вид const: оператор;

End

В чистом Паскале нет else(default) константы.

В С, C++, Java, C#:

switch (expr) of {

case 1:... break;

...

case n:... break;

default:... break;

}

break - указатель на переход на конец структуры, если его нет, то дальше выполнится следующий case. Если в С++, С, Java - break было писать не обязательно после каждого case, то в С# стало обязательным (ошибка компиляции). Если в С# мы хотим после завершения данного case перейти на следующий надо использовать оператор перехода.

Модула - 2:

CASE expr OF

Список значений1: s11; s12; …; s1N |

Список значений2: s21; s22; …; s2N |

….еще списки значений

ELSE ……

END

Ввиду возникающей синтаксической неоднозначности со списком значений вводится спецсимвол – вертикальная черта |

Ада:

Case expr of

when <список констант иди диапазонов> => оператор1

...

when <список констант иди диапазонов> => операторN

when others => операторы

End case;

Операторы циклы.

Выделяют 4 вида цикла:

1. Пока

While B loop.. End loop (ADA)

WHILE B DO.. END (Modula - 2)

While (B) S(C, C++)

While B do S(Pascal)

2. До

REPEAT UNTIL B; (Modula - 2)

do S while (B); (С, C++)

3. FOR

for v:= r1 to t2 do S(Pascal).

for(e1; e2; e3) S; (C++, C)

в Java, C# аналогично С, только там на каждой итерации осуществляется квазистатический контроль, то есть A[i] - должен на самом деле существовать, чтобы не вызвать ошибки.

FOR V:= E1 TO E2[STEP E3(целое значение)] DO END(Модула - 2) - можно было задавать шаг. Он мог быть как отрицательным так и положительным. E1, E2 - типы, к которым применима операция сложения и вычитания.

В 1993 - вышел Оберон - 2, который по идее является минимальным полным языком для написания любой программы, куда вошел и цикл for.

for v in <диапазон> loop.. end loop

for i in A'RANGE loop S:= S + A(i); end loop

for i in A'FIRST..A'LAST loop S:= S + A(i); end loop; (Ада)

4. Бесконечный цикл

LOOP

... IF B THEN... EXIT

END (Модула - 2)

 

while (1) {... break...}

for(;;) {... break...} (C++, C)

 

Loop

...

when B => exit

...

end loop (Ada)

goto - перейти на помеченное место в программе. В Модуле - 2, Java.

Обероне отсутствует.

Для организации не локальных переходов:

setjmp, longjmp – В Си++ используются для обработки ошибок.

throw, trace – Обработка исключений

Также существуют специальные операторы для организации параллелеризма

Lock(obj) {блок} – Си#. Поток управления блокируется, если блок кем-то используется

accept, select – Ада

Особенности реализации циклов-итераторов в современных ЯП.

Очень полезен. Когда мы ищем максимальный и минимальный элемент контейнера, например.

Представим себе массив:

int[ ] a = new int[N];

for(int i=0; i<a.Length; i++)

{

Что-то делаем с a[i]………

}.

Не лучший способ записи. Результат может зависеть от порядка просмотра.

a[i] – это всегда некоторое вычисление. Что есть в C#, а в С не будет никогда? Конечно, проверка выхода за границу массива.

foreach(double v in a)

{

.............

};//управляющая переменная v просто последовательно принимает значение элементов массива.

Так как квазистатический контроль на каждой итерации цикла считается неэффективным в С# был придуман еще один вариант цикла for - особая форма цикла.

foreach (T o in C) S;

int a[];

foreach (int x in a) S = S + x;

C - произвольная коллекция.

тип T должен наследоваться от IEnumerable, в которой входит такой метод, как получить следующий элемент. В Java сей цикл был реализован в 2005 году.

В общем случае контейнер языка C# - это класс, поддерживающий интерфейс IEnumerable. И компилятор будет обрабатывать конструкции подобных классов специфическим образом.

GetEnumerator(); //выдает iterator, нужный для пробегания по элементам, а не по индексам.

Также у класса поддерживающего интерфейс IEnumerable, есть свойства Current и метод MoveNext()

Создатели языка Java сделали еще метод hasNext().

Java

используется для поэлементного просмотра коллекций (цикл for-each). Она имеет вид;

for (T v:Coll)S

Здесь Coll — коллекция элементов (типа T или приводимых к типу T).

Переменная v на каждой итерации цикла принимает значение очередного элемента коллекции.

Для того, чтобы объекты класса-коллекции могли появляться в цикле for-each, класс должен реализовать интерфейс Iterable

4. Процедурные абстракции

Подпрограммы и сопрограммы. Операторы возврата и возобновления.

Подпрограммы

Почему «подпрограмма?» Управление входит в подпрограмму только через имя блока. И возвращается туда, где была вызвана подпрограмма, и ни в какую другую точку вернуться не может.

CALLER – вызывающий подпрограмму(надпрограмма)

CALLEE – вызываемая подпрограмма

Сопрограммы

Впервые механизм сопрограмм был придуман для компилятора COBOL.

При вызове сопрограммы управление передается в точку, непосредственно следующую за местом, где оно покинуло сопрограмму.

Сопрограммы – фактически квазипараллельные процессы.

Модула-2

Вызов сопрограммы аналогичен длинному переходу на некоторый абстрактный адрес, по которому находится команда сопрограммы, с которой нужно начать выполнение. Но, помимо этого, нужно ещё как-то запомнить адрес возврата и другую служебную информацию, передать входные параметры, наследуется часть контекста. Для этой цели Вирт в своём языке Модула-2 ввёл тип данных ADDRESS (то же самое, что и

«void *»).

Этот тип данных является потенциальной дырой в системе безопасности, т.к. любой указатель «Т *» автоматически приводится к «void *», и возможно обратное явное преобразование «Т *» = (Т *)«void *».

Итак, в Модуле-2 вызов сопрограммы имеет такой вид:

NEWPROCESS(P, C,N);

Где P – процедура без параметров типа PROCEDURE, который является встроенным, C – переменная типа ADDRESS. N - размер области для «запоминания» информации. Область начинается с адреса C

PROCEDURE NEWPROCESS(P: PROCEDURE; VAR C: ADDRESS; N: INTEGER);

Передача управления от одного процесса другому на уровне сопpогpамм осуществляется процедурой "Передать управление от процесса P1 процессу P2". В Модуле-2 эта процедура выглядела как

PROCEDURE TRANSFER(VAR P1,P2: ADDRESS);

При этом в переменную P1 записывается запись реактивации этого процесса, а значение переменной P2 определяет запись активации процесса P2.

RESUME; – оператор языка.

В современных языках сопрограммы трансформировались в понятие потока.

.Net Thread Квазипараллельный поток

C# 2.0:

foreach(T x in C)

Тип T должен реализовывать интерфейс IEnumerable. Этот интерфейс содержит метод GetEnumerator(), который возвращает объект некоторого типа, который должен реализовывать интерфейс IEnumerator со свойствами Current, методом Reset и методом bool MoveNext(). Любой класс, поддерживающий интерфейс IEnumerable должен содержать класс, поддерживающий IEnumerator.

yield-операторы в C# 2.0:

yield return <expression>;

yield break;

Итератор – процесс(сопрограмма), выдающий последовательно очередные элементы коллекции тогда, когда они понадобятся. yield-оператор используется в блоке итератора для предоставления значения объекта перечислителя или для сообщения о конце итерации. Т.е. это не простой «return» или «break», а оператор, совмещающий в себе дополнительно работу по переходу между сопрограммами (от процесса-итератора в

основной процесс). Выражение expression вычисляется и возвращается в виде значения объекту перечислителя; выражение expression должно неявно преобразовываться в тип результата итератора.

Public class List

{

//using System.Collections;

public static IEnumerable Power(int number, int exponent)

{

int counter = 0;

int result = 1;

while (counter++ < exponent)

{

result = result * number;

yield return result;

}

}

 

static void Main()

{

// Display powers of 2 up to the exponent 8:

foreach (int i in Power(2, 8))

{

Console.Write("{0} ", i);

}

}

}

/* Output:

2 4 8 16 32 64 128 256 */

С точки зрения современных языков программирования сопрограммы оказались глубоко зарыты в потоках и в итераторах. Явно остались лишь те подпрограммы, у которых есть 1 вход и 1 выход.

Процедуры и функции в современных ЯП.

Передача параметров: семантика и способы реализации.

· Через глобальные данные

· Через параметры

Виды формальных параметров(семантика):

• Входные (in) – должны быть определены до входа

• Выходные (out) – должны быть определены к моменту выхода

• Вх/Вых(InOut) – и то и другое

Способ передачи – способ связывания фактических и формальных параметров:

• По значению (семантика - in) (При вызове подпрограммы фактические параметры

копируются в Запись Активацаии)

• По результату (семантика – out) (При выходе из подпрограммы из записи активации

формальные параметры копируются в фактические)

• По значению/результату (семантика – InOut) (При вызове подпрограммы фактические параметры копируются в Запись Активацаии, При выходе из подпрограммы из записи активации формальные параметры обратно копируются в фактические)

• По адресу(по ссылке) (семантика - любая) (При передаче по Адресу в Запись активации

копируется адрес фактического параметры. Именование и разыменование происходят

автоматически)

• По имени

В Pascal 2 способа передачи параметров – по ссылке и по значению.

Если у параметра присутствует Var, то объект передается по адресу. А если не присутствует, то по значению.

Ада83:

Квалификаторы: in, out, inout

Procedure P(int X:T;inout Y:T;out Z:T);

X может быть выражением типа T. Компилятор может вставлять квазистатические проверки. Эффект процедуры – модификация Y и Z. Каков способ передачи определяет компилятор (что не есть хорошо, т.к. различные компиляторы в одной и той же ситуации могут выбрать разные способы передачи, что приведёт к различной работе программ).

Запись активации

…..

……

Место для формальных параметров

Энтропия – явление, при котором программа может выдавать различные результаты при одних и тех же исходных данных. Если в программе есть энтропия, то это очень плохо. Очевидно, что при программировании на Ада риск энтропии значительно повышается, т.к. не известно какой способ передачи выберет в этот раз компилятор

В Фортране обычно параметры передаются по адресу, но когда передаётся простой объект данных, чтобы не происходило лишних операций разыменования, можно передавать «по значению и результату»(/<параметр>/)

• В Ада-95 – по значению, по ссылке

• В Си – не определяется семантика использования. Способ передачи только по значению

• В Си++ – по значению, по адресу (ссылке). Контроль семантики: in – ссылка константная, out, inout – не константна

void f(T &); //Компилятор считает, что f будет менять значение => константный объект

//передавать нельзя

Это указание для компилятора, чтобы он следил за соблюдением семантики.

В C#, Delphi(TurboPascal+объектно-ориентированная надстройка) – языках с референциальной моделью данных – все параметры автоматически передаются по ссылке.

Типы данных C#:

· референциальные

· типы-значения

o примитивные типы данных (все передаются по значению)

типы данных структуры

С#

void f(T x) {….;}

……

T a; // a – ссылка, если Т – объект

f(a); // передаётся ссылка

Оба языка поддерживают идею примитивных типов (которые в C# являются подмножеством типов-значений — value types), и оба для трансляции примитивных типов в объектные обеспечивают их автоматическое «заворачивание» в объекты (boxing) и «разворачивание» (unboxing) (в Java — начиная с версии 1.5).

Тип-значение(value type) – тип, объекты которого передаются по значению. Если где-то нужен объект такого типа, то отводится место под сам объект. типами-значениями являются простые (примитивные) типы данных и структуры

Референциальный тип – тип, объекты которого передаются по ссылке. Если где-то нужен объект такого типа, то отводится место под адрес. Референциальными типами являются классы (любой массив – наследник класса Array, строка это объект класса String, и т.д.)

В принципе, в C# можно передавать объекты простых типов в функции с помощью классов-обрёток, но C# также поддерживает явное описание передачи параметров по ссылке – ключевые слова ref и out. «ref» реализует семантику inout, а «out» реализует семантику out. При использовании out компилятор вставляет квазистатический контроль на наличие в методе присваивания значения, зато не требует инициализированность фактического параметра перед вызовом метода.

void f(ref int x){x = -3;}

….

int a = 0;

f(ref a); // а будет передано по ссылке, если бы объект «а» был структурой, то он так же // передался бы по ссылке

Java:

Все передается по значению, но для классов в созданный объект копируется адрес (ну то есть реально это все равно передача по ссылке)

Структур в Java нет.

Передача объектов примитивных типов в методы «как по ссылке» выполняется через классы-обёртки:

void f(Integer X){…X = ….; }

…..

int i = 1;

Integer px = new Integer(i);

f(px);

i = px;

Integer – класс-обёртка для примитивного типа «int». Суть способа – преобразовать объект примитивного типа в объект класса и работать внутри функции с объектом класса.

Алгол-60

Передаём сам объект «как он есть» (по имени). Фактически передаётся его идентификатор как строчка. Далее в теле процедуры идентификатор формального параметра заменяется на идентификатор фактического.

Обоснование невозможности написание процедруры swap на Algol-60:

procedure Swap(a,b); //a, b передаются по имени

Begin

T tmp;

tmp:= a; a:= b; b:= tmp;

End;

….

swap(i, A[i]);

T tmp;

tmp:= i;

i:= A[i];

A[i]:= tmp;// A [ A[i] ]:= i; неправильно!!!

swap(A[i], i);

T tmp;

tmp:= A[i];

A[i]:= i;

i:= tmp;// i:= A[i] – всё правильно

Решение проблемы: С каждым параметром передавалась процедура thunk, которая выполнялась при каждом обращении к фактическому параметру.

В С++ можно задавать параметры по умолчанию: void f(int a = 4){ …;}

В C# эту возможность убрали. Вместо этого предлагается использовать перегрузку:

f(){ f(1, 2); }

f(int i){ f(i, 2);}

f(int i, int j) { …; }

Статический полиморфизм и перегрузка имен подпрограмм.

Подпрограммные типы данных. Проблемы, связанные с

подпрограммными типами данных и способы их решения в современных ЯП.

Ада 83, Java – нет.

Передача подпрограмм, как параметров.

Присваивание [:=]

Вычисление [()]

В Pascal введено 2 вида подпрограмм как формальных параметров: процедуры и функции. Аналогичный подход можно заметить и в других языках.

Значения подпрограммного типа данных – это набор констант, образующийся именами соответствующих процедур и функций.

Ада 83: generic не только для ТД, но и для процедур, функций.

//generic – параметризованный тип данных. Отметим, что параметризация в родовых сегментах происходит во время трансляции

с/с++: typedef void (*f)(int);

Отсюда, процедурный тип – указатель.

Проблема в том, что в Ада 83 и Java отказались от указателей, т.е. и от П/П ТД.

//В Java целиком, в Ада частично.

Ада 95:

type Func_Pointer is access function (L,R: float) return Boolean;

function Compare (X,Y: float) return Boolean … end Compare;

F: Func_Pointer

F:=Compare’access

С++, Modula-2, Оберон

void f(int) – это прототип функции, объявление некоторой функциональной константы. Если перед ней поставить typedef, что имя функции станет синонимом нового типа:

Модула-2, Оберон:

TYPE FUNC_INT = PROCEDURE (L,R: REAL): BOOLEAN;

PROCEDURE COMPARE (X,Y: REAL): BOOLEAN;

VAR F: FUNC_INT;

F:=COMPARE;

C#: Делегаты(расширение П/П ТД)

Операции делегата:

· присваивание (инициализация)(=)

· добавление делегата(+=)

· «убирание» делегата(-=)

Вызов (скобочки: ())

this хранится вместе с указателем на функцию. Делегатом может быть и статический и нестатический член класса.

1.Параметр функции – делегат.

delegate int Processor(int i);

Prcessor p = new Processor(func);

Толькo += или -=.

Механизм делегатов инкапсулирует свойства процедурных типов данных, сводя к минимуму недостатки данного типа

Таким образом, делегат в С# - заменитель процедурного типа данных.

5. Определение новых типов данных. Логические модули. Классы.

Концепция уникальности типа в традиционных языках



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-02-16 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: