Популярные услуги

Все письменные КМ под ключ за 7 суток! (КМ-1 + КМ-2 + КМ-3 + КМ-4 + КМ-5)
Все 4 контрольные точки за 7 суток
Оба семинара по программированию под ключ! КМ-2. Разработка циклических алгоритмов + КМ-3. Функции и многофайловые программы в Си
КМ-3. Основы J⁣a⁣v⁣a⁣S⁣c⁣r⁣i⁣p⁣t - обработка событий, проверка ввода данных в форму
Повышение уникальности твоей работе
Одно любое задание в mYsql
Все письменные КМ под ключ за 3 суток! (КМ-6 + КМ-7 + КМ-8 + КМ-9 + КМ-10)
Любой реферат по информатике
КМ-6. Передача параметров между сценариями (скриптами) PHP. Отправка данных на сервер с помощью форм. - Выполню за вас.
Любой реферат по объектно-ориентированному программированию (ООП)

Лекция 9

2021-03-09СтудИзба

Лекция 9

  Различия между базисами ЯП достаточно тривиальны. Особенно это проявляется на примере операторного базиса.

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

1) Модульность. Включает в себя

§  разделение на физические модули (раздельная трансляция)

§  концепцию процедурной абстракции.

2) Разделение данных

  С помощью процедурных абстракций создаются библиотеки стандартных подпрограмм. С помощью раздельной трансляции объединяется работа нескольких программистов в одно целое (индустриальный проект не может быть создан одним программистом).

Рекомендуемые материалы

  Алгол имел процедурные абстракции, немного более развитую структуру данных, чем FORTRAN, но у него не было понятия раздельной трансляции. Поэтому всерьез использовать Алгол как коммерческий язык было невозможно. FORTRAN при всех его недостатках до сих пор остается индустриальным ЯП. В 60-ые г.г. на FORTRAN были созданы мощные успешные коммерческие проекты.

  Самое простое и самое основное из средств развития – процедурная абстракция.

   Глава 4: Процедуры и функции.

  Впервые появились в языке FORTRAN. Программирование в терминах процедур и функций является базисным навыком программиста. Процедура –независимый кусок управляющих конструкций, который содержит заголовок, содержащий имя и параметры, т.е. процедура – параметризованная абстракция.


  заголовок


Первые коммерческие продукты – переносимые библиотеки стандартных подпрограмм. Библиотеки, которые были созданы в 60-ые г.г. продолжают успешно существовать до сих пор. В этом одна из причин популярности FORTRAN среди его достаточно многочисленных пользователей. Но в FORTRAN очень неудобный способ взаимодействия различных подпрограмм. Было 2 способа взаимодействия:

1. через передачу параметров.

2. через общий блок. Была общая память, которая доступна всем программам. Общий блок описывался в каждой подпрограмме с помощью директивы COMMON. Таким образом мы в каждой подпрограмме ссылались на одни и те же данные. Интересно, что первоначально понятие общего блока было введено исключительно с целью экономии места.

      SUBROUTINE S(X, Y, Z)

       COMMON …

       …

      END

  Внутри процедур существовали локальные переменные, но все они, также как и общие блоки располагались в статической памяти, т.к. в FORTRAN вся память была статичной. А, следовательно, не было ни понятия рекурсии, ни вложенных подпрограмм.

  В Алголе 60 появились локальные среды ссылок. Внутри одной процедуры можно было описывать другие процедуры, которые локально ссылались на переменные, описанные внутри объемлющих процедур. Глубина вложенности могла быть произвольной. Появилось понятие рекурсии, и у каждого рекурсивного вызова должна быть своя порция одноименных локальных переменных. Возник стек. В первых компьютерных архитектурах стека не было. В первых реализациях Алгола компилятор определял, является ли процедура рекурсивной. Если не является, то реализовывал ее в стиле языка FORTRAN. А рекурсивные процедуры компилятор программировал иначе, создавая для хранения локальных переменных системный стек. Даже в такой распространенной архитектуре, как IBM 360, понятие стека аппаратно реализовано не было. Программист, пишущий компилятор, должен был промоделировать соответствующие концепции. Во всех без исключения компьютерных архитектурах  начиная с конца 60-ых г.г. начинают появляться конструкции, которые явным образом поддерживают понятие процедуры в ЯП высокого уровня.  

   Механизм передачи управления.

  С современной точки зрения процедура представляет собой структурную конструкцию, т.е. она имеет один вход и один выход. Вход идентифицируется по имени. В момент входа происходит связывание формальных параметров функции или процедуры с фактическими параметрами. В большинстве ЯП есть явный оператор возврата

RETURN

если это возврат из функции, то

RETURN выражение

Синтаксис этой конструкции практически не меняется с 60-ых г.г., когда она появилась в языке FORTRAN. Этот оператор может стоять в произвольном месте подпрограммы, но главное, что со структурной точки зрения конструкция имеет один вход и один выход.


 

              

   В ранних ЯП существовали процедуры с множественными входами. Точки входа могли быть разными, и с разными наборами параметров.


                            

                               

                             


В FORTRAN 77 до сих пор осталась конструкция ENTRY, которая позволяет по-разному именовать одну и туже подпрограмму. Надежность подобного рода конструкций сомнительна.

  Во многих ранних ЯП были так называемые параметры-метки. Можно было указать в качестве фактического параметра метку. Параметры нумеровались от 0 до N, и RETURN I означал, что возврат осуществляется не в место вызова, а в некоторую точку программы, на которую указывал соответствующий аргумент-метка.

…                           P

CALL P                  …

…                           RETURN

…                           P

CALL P                  …

…                           RETURN I

I:

Это завуалированная форма оператора перехода. Конструкция не структурная.

  В ЯП была еще одна концепция, которая также имела один вход и один выход. Это сопрограмма. В случае с подпрограммой одна подпрограмма главная, другая – подчиненная. Их отличие в том, что выполнение процедуры всегда начинается с первого оператора (в современных ЯП у процедуры только один вход). Главная программа знает имя подпрограммы, а подпрограмма не знает, кто ее использует.

главная        P

CALL P      RETURN


CALL P

              

Из понятия подпрограммы возникает понятие сопрограммы, если сделать главную и подчиненную равноправными. В подпрограммах не симметричны понятия вызова и возврата. В сопрограммах CALL и RETURN объединяются в одну конструкцию RESUME (возобновить).

S1                        S2

RESUME S2       RESUME S1


RESUME S2       RESUME S1


                                 

В ранних ЯП понятие сопрограммы появилось потому, что оно очень хорошо моделировало семантику квазипараллельных процессов, и это один из способов реализации параллелизма на однопроцессорной машине. RESUME – явная передача управления. Отличие от концепции процессов в ОС – ОС может насильно с помощью прерывания по времени передать управление от одного процесса к другому.

  Уже в начале 60-ых г.г. многие коммерческие проекты были сделаны с помощью понятия сопрограммы. Это понятие появилось во многих ЯП: в Симуле 67,  в Модуле 2 (достаточно низкоуровневое)…

  В современных языках понятия сопрограммы нет. Основным назначением сопрограмм было моделирование квазипараллельных процессов, а в большинстве современных ОС концепция параллелизма присутствует. Имеются различия в реализации параллелизма в разных ОС.

  В С#, C++ и Delphi концепции, которая поддерживает параллелизм явным образом, нет.

  В языках Ада и Java концепция параллелизма есть. Ада в свое время претендовала на роль универсального ЯП, который должен собой заменить все другие языки, и поэтому параллелизм в нем явным образом присутствует. В Аде 95 были существенные добавления к механизму параллелизма, который за время прошедшее с момента принятия первого стандарта Ады очень сильно критиковался. Java не претендовала на роль универсального ЯП, но она претендовала на роль мультиплатформной системы, т.е. код, написанный на Java, должен выполняться на всех системах, где установлена виртуальная Java-машина. Поэтому создатели языка были обязаны включить параллельные конструкции в ЯП, чтобы программа не зависела от операционной среды.

  Какие-то частные конструкции, которые моделируют параллелизм, в современных ЯП излишни. Можно использовать соответствующие библиотечные средства. При этом возникает системная зависимость. Вместо сопрограммы, можно использовать концепцию легковесного процесса, которая есть практически во всех современных ОС. В Java концепция легковесного процесса (потока, нити) присутствует явным образом. Можно сказать, что в C# концепция потока также присутствует потому, что C# основан на платформе .NET, в которой есть управление процессами. Но эти средства находятся не в самом языке, а в соответствующей системной библиотеке.

   Передача данных между главной программой и подпрограммой.

  В отличие от передачи управления, передача данных может быть организована по-разному.

  Передача данных возникает в общем случае в двух местах: в момент вызова и в момент возврата. В момент вызова передается информация из фактических параметров в формальные. В момент возврата может передаваться информация как из формальных параметров в фактические, так и возвращаемое значение функции. В принципе в языке можно обойтись вообще без функций, ограничившись процедурами, которые модифицируют свои параметры. Это не удобно. Кроме того, если мы умеем передавать информацию из формального параметра в фактический, то достаточно просто организовать передачу возвращаемого значения функции. Рассмотрим передачу информации между формальными параметрами и фактическими, и все сказанное распространяется и на возвращаемое значение функции.    

  Есть три семантики передачи параметров:

1) Ввод (режим in). Информация передается только из фактического параметра в формальный. От фактического параметра требуется статус определенности, и его значение используется в вычислениях. Например: sin(x). Для вычисления значения надо знать значение х. Значение фактического параметра при вычислении никак не меняется.

2) Вывод (режим out). Информация передается из формального параметра в фактический. Например: Pop(S, x). S – стек, х –фактический параметр, который должен получить свое значение из соответствующего формального параметра. При входе от фактического параметра не требуется статус определенности, в него передается информация при выходе, и он обретает статус определенности. При выполнении процедуры состояние фактического параметра меняется.

3) Ввод Вывод (режим in out). Смешанная семантика.

  В языке Ада  83 при описании формальных параметров процедур и функций требуется указать режим передачи соответствующего формального параметра. Например:

function Sin(x: in REAL) return REAL;

procedure Pop(S: in out Stack, x: out INTEGER);

Если Pop выполняется корректно, то переменная, указывающая на вершину стека, меняет свое значение, т.е. меняется состояние стека. Следовательно, параметр S должен находится в режиме вывода. В то же время от него требуется статус определенности. Поэтому S – типичный пример параметра in out.

  В остальных языках высокого уровня вместо того, чтобы указывать семантику передачи параметра, программист должен указывать способ передачи параметра, который он выбирает сам. В языке Ада нужный способ реализации семантики выбирал компилятор.

  Способы передачи параметров:

1) По значению (реализует семантику in)

2) По результату (реализует семантику out)

3) По значению/результату (реализует семантику in out)

4) По ссылке (адресу)

5) По имени

  Первые три способа основаны на том, что для формального параметра выделяется место в локальной памяти. Эта память будет находиться в стеке, что следует из семантики вызовов подпрограмм. Т.е. формальный параметр можно рассматривать как локальную переменную соответствующего типа, и в рамках этих трех способов они ничем не отличаются, за исключением того, что в какие-то моменты времени происходит обмен информации между формальными и фактическими параметрами. Передача параметра по значению означает, что перед вызовом происходит копирование фактического параметра в формальный. Передача по результату означает, что в момент возврата происходит обратное копирование –  формального параметра из локальной памяти в соответствующий фактический параметр. Третий способ означает, что в момент вызова происходит копирование из фактического параметра в формальный, а в момент возврата – из формального в фактический. Т.е. это комбинация первых двух способов.

  Проблема этих способов передачи в том, что когда формальный параметр занимает много места, возникают большие накладные расходы как на память (мы должны отводить локальную память такого размера), так и на передачу информации. Например: нужно написать процедуру, которая вычисляет максимальный элемент в массиве. Если мы используем передачу параметров по значению, накладные расходы на передачу информации сопоставимы с накладными расходами на вычисление. Поэтому были введены альтернативные способы передачи параметров.

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

  В С единственный способ передачи параметров – по значению. Этот способ реализует только семантику in. В случае, если мы хотим реализовать семантику in out в языке С, мы должны сами реализовать передачу параметра по ссылке. Т.е., если мы хотим написать процедуру, меняющую значение своего аргумента, мы должны передавать вместо самого аргумента его адрес

void f(int *p)

и далее везде, где требуется значение аргумента надо явно разыменовывать указатель: *p.

  Если в языке есть способ передачи по ссылке, значит, в языке есть возможность делать все это автоматически. Такой способ передачи есть в языке Паскаль и всех языках, которые на нем основаны. Если параметр описан

VAR X:T;

то вместо него передается соответствующий адрес. И везде, где встречается Х

X:= Y;

Y:= X;

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

  В случае, если в языке нет возможности передачи параметра по ссылке то, чтобы язык был достаточно мощным необходимо, чтобы имелись явные операции взятия адреса ( в языке С  это - &) и его разыменования (в языке С это - *).

  Во всех, рассматриваемых нами ЯП, есть передача параметров по значению. Большинство компьютерных архитектур явным образом поддерживают механизм передачи параметров – в современных вычислительных архитектурах аппаратно реализован стек. Как следствие, передача параметров по значению есть везде.

  Самый универсальный способ передачи параметров – четвертый. Если у нас есть адрес переменной, мы можем делать с этой переменной все, что захотим. Но передача параметров по значению с точки зрения реализации эффективней, т.к. передача параметров по ссылке влечет за собой косвенную адресацию, которая менее эффективна, чем прямая адресация, которой мы добиваемся с помощью передачи параметров по значению.

  В первых реализациях языка FORTRAN был единственный способ передачи параметров – по ссылке, т.к. он наиболее универсален. В конкретной реализации FORTRAN можно было изменить значение константы 1 следующим образом. Передаем константу 1 по ссылке как фактический параметр, меняем в процедуре значение этого параметра. Учитывая то, что большинство реализаций под константы отводит место в статической памяти, значение константы потеряно. Это свидетельствует о том, что механизм передачи информации, который не сопровождается защитой соответствующих параметров, крайне ненадежен. С другой стороны, организация передачи по ссылке явным образом, как это есть в языке С, тоже неудачное решение. Поэтому Страуструп ввел в С++ специальный ТД ссылка, одним из основных применений которого было введение в язык нового способа передачи параметров – по ссылке.

T & x

Т.е. в С++ так же как и в Паскале программист может выбирать соответствующий способ передачи параметра – либо по значению, либо по ссылке.

  Способ передачи параметров по значению  реализует семантике in, а способ передачи параметров по ссылке – in out. Но может возникнуть ситуация, когда необходимо передать большой формальный параметр в режиме in, а с точки зрения эффективности реализации его необходимо передавать по ссылке, т.е. in out. Если мы передаем массив в языке Паскаль по ссылке, мы можем по ошибке модифицировать элемент массива, и компилятор сообщения об ошибке не выдаст. Страуструп хотел сделать передачу параметра по ссылке более надежной, поэтому он ввел константную ссылку.

const T & x

Она означает, что программист по каким-то причинам передает параметр по ссылке, но при этом он хочет реализовать семантику in. При любой попытке изменить значение параметра внутри процедуры компилятор выдаст сообщение об ошибке, т.к. это ссылка на константный объект.

  В языке Ада 83 программист фиксирует только семантику для контроля компилятором. Т.е. если параметр in, то меняться он никак не может. Компилятор сам должен выбирать соответствующий способ реализации. В Аде 95 если параметр содержит массив, он всегда должен передаваться по ссылке, т.к. в языке Ада есть различие передается параметр по значению/результату или по ссылке. Оно проявляется в очень редких случаях. Например:

P(X, Y: in out T)

Если фактические параметры X и Y различны, то с точки зрения программиста никакой разницы нет передаются данные по значению/результату или по ссылке. Пусть в теле процедуры

X:= 1;

…                   может случиться аварийная ситуация (деление на 0, …), возникает

                       исключение (exception) и управление покидает процедуру.

Y:= 2;

Пусть есть переменная

A: T;

Если мы вызываем

P(A, A);

Если процедура заканчивается нормально, А получит значение 2 вне зависимости от способа реализации передачи параметров. Если при вызове между двумя операторами присваивания возникает исключение, то значение А будет зависеть от способа передачи параметров. Если передача по значению/результату, то т.к. X и Y меняют значение, А должно поменять значение в момент нормального выхода из процедуры. В случае, если возникает исключение, копирования из формального параметра в фактический не произойдет, значение А останется прежним. Если мы передаем параметр по ссылке, любое изменение формального параметра тут же отражается на фактическом, следовательно, значение А станет равным 1. Самое неприятное то, что это различие сказывается при переносе программы с одного компилятора на другой, в которых приняты разные способы передачи параметров. Когда программа работает нормально, оба компилятора работают эквивалентно. Но, хоть и редко, могут возникать описанные выше ситуации. Следовательно, этим снижается мобильность программ. Поэтому создатели нового стандарта языка Ада постулировали: когда используется семантика in, способ передачи параметра выбирает компилятор. Для массивов и для записей, которые содержат большую информацию, он выбирает способ передачи по адресу. Для простых переменных он всегда выбирает способ передачи параметра по значению. Для всех in out режимов компилятор Ада 95 всегда выбирает способ передачи по ссылке вне зависимости от того, передаваемая переменная простого ТД или сложного составного. В результате улучшается переносимость программ с одного компилятора на другой.

  Модула 2 и Оберон наследуют семантику Паскаля. Программист выбирает либо семантику in, либо семантику in out.

  Delphi также наследует семантику Паскаля, но семантика классов в Delphi такая же как в Java и C#. В Java все ТД делятся на простые базисные ТД и ссылочные типы, к которым относятся массивы, классы и интерфейсы.

void f(int x) {…}

Способ передачи для всех простых ТД по значению. А имена всех составных ТД являются ссылками, поэтому они передаются по ссылке.

void f(String a) {…}

а передается по ссылке, поскольку String –имя стандартного класса.

  В Delphi соответственно

procedure P (X: T)

Если Т – простой ТД, то Х передается по значению. Если Т – имя класса, значит Х – ссылка на объект класса Т. Следовательно Х передается по ссылке.

procedure P (VAR X: T)

Если Т – имя класса в языке Delphi, в этом случае передается ссылка на ссылку. И в том, и в другом случае мы имеем право модифицировать состояние фактического аргумента, поскольку нам доступна ссылка. Например:

X.Free

Передавать с помощью VAR надо, когда мы в процедура Р хотим Х присвоить какое-нибудь значение.

X:= T.Create

В остальных случаях разницы нет, за исключением того, что передавать с помощью VAR менее эффективно.

  В Java можно написать процедуру, меняющую значение своего параметра простого ТД, используя классы-обертки. Параметр простого ТД передается по значению. Для каждого простого ТД существует стандартный класс-обертка. Имена стандартных типов начинаются с маленькой буквы, имена соответствующих им классов – с большой.

int     -     Int

char  -     Char

…    …    …  

Здесь мы сталкиваемся с концепцией рефлексии. В  Java есть специальный пакет Java.lang. Внешне он выглядит как обычный стандартный пакет языка Java. Отличие стандартной библиотеки от компилятора в том, что компилятор менять не рекомендуется, а стандартную библиотеку поменять можно. Можно написать свою реализацию библиотеки.  Классы из пакета Java.lang внешне ничем не отличаются от классов из библиотеки. Но часть семантики всех этих классов зашита в компиляторе. В частности, классы обертки – классы из Java.lang. Опишем некоторую функцию, в качестве формального параметра которой будет указан не объект простого ТД, а объект класса-обертки.

void f (Int x) {x= 1;}

Т.к. это класс, то объект передается по ссылке.

int a;

f(a);

Компилятор не выдаст сообщение о несоответствии типов. В языке Java никакие неявные преобразования не разрешены, кроме преобразований для классов-оберток, которые входят в Java.lang. В данном случае компилятор произведет соответствующую обертку

f(Int(a));

    Тем самым решена проблема моделирования любой семантики. Если мы хотим для простых ТД реализовывать семантику in out мы должны описывать соответствующий формальный параметр как объект не самого простого ТД, а соответствующего ТД обертки.

  Ко многим свойствам ТД можно добраться не с помощью каких-то констант типа maxint, minint, …, а как к свойствам соответствующего класса обертки. Это верно для всех классов обертки.

  В C#, как и в языке Java, классы имеют ссылочную семантику, в отличие от простых ТД. Кроме этого в С# есть структуры.

struct

Они отличаются от структур в С++. Внешне они выглядят как классы, но они значительно более ограничены. Они не могут наследоваться явно, а наследуются только неявно из ТД object. От них ничего не может наследоваться. У них не может быть конструкторов по умолчанию. Они не имеют ссылочной семантики. Если структура описана как локальная переменная, она размещается в стеке. (Для класса в стеке размещалась бы только ссылка.) Поэтому в С# появилось понятие Boxing. В случае, когда надо передавать структуру как формальный параметр, структура преобразуется в экземпляр некоторого класса, и передается ссылка на экземпляр этого класса. Т.е. Boxing – это преобразование из не ссылочной структуры в ссылочный класс.

  Для простых ТД в языке есть два ключевых слова – ref и out. Ключевое слово ref означает способ передачи по ссылке.

void f(ref int a);

ref реализует семантику in out, т.е. от формального параметра требуется значение определенности и он может менять свое значение. В C# при появлении переменных всем ссылочным переменным присваивается нулевое значение, а всем переменным простого типа присваивается несуществующее значение. При попытке

i:= a;

если а имеет несуществующее значение компилятор выдает ошибку, также как и при попытке разыменовать нулевой указатель. Поэтому, если мы передаем переменную как ref, а она не определена, компилятор сгенерирует сообщение об ошибке. Причем это будет не в момент попытки обратиться к а, а в момент передачи параметра. Ключевое слово out говорит о том, что реализуется семантика out. От параметра не требуется статуса определенности.

int x;

f(x);

Во время выполнения возникнет исключительная ситуация, и будет выдано сообщение об ошибке. Если описать

void f(out int a);

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

  Передача параметров по имени впервые появилась в языке Алгол 60. Она означает, что вместо текста формального параметра  везде в теле процедуры, к которой мы обращаемся, подставляется текст фактического параметра в том виде, в котором он записан. С формальной точки зрения могут возникнуть конфликты.

P(i);

Если при этом внутри Р описана другая локальная переменная i, возникает конфликт. Этих конфликтов можно избежать с помощью локального переименования имен. Например, локальным переменным можно изначально присваивать уникальные имена, которые нигде больше не повторяются. Способ передачи параметров по имени очень простой и естественный. В современных ЯП он не используется. Пример: В Алголе 60

integer i;

integer array [1..N] a;

procedure P(x: integer);

Пусть х передается по имени. Пусть внутри процедуры Р

i:=3;

x:=1;

end;

где i – глобальная переменная. Далее

i:=1; a[1]:=0;

P(a[i]);

В случае если параметр передается по ссылке (в данном случае семантика out), a[1] получит значение 1, i – 3.

В случае, если параметр передается по имени, везде вместо х подставится a[i]. а[1] останется равно 0, а элемент с номером 3 поменяет свое значение на 1.

  Классическое упражнение, которое в частности есть в книжке Себесты в главе, посвященной реализации процедур: Доказать то, что в языке Алгол 60 нельзя написать процедуру Swap(a, b) , которая меняет местами значения своих аргументов. В Алголе 60 есть всего 2 способа передачи параметров – по значению и по имени. Поскольку параметры меняют свои значения их нужно передавать по имени. Вводится локальная переменная t.

t:= a

a:= b

b:= t

Предлагается вызвать

Swap(a[i], i)

Swap(i, a[i])

В ЯП с передачей по ссылке получится один и тот же результат – a[i] и i поменяются местами. В случае, если передача параметра по имени, в первом случае работать будет, а во втором нет. Т.к. в первом случае сначала изменяется a[i], а во втором – сначала i, и a[i] будет уже другое.

  Т.е. передача параметров по имени в случае императивных ЯП создает достаточно неприятные побочные эффекты. Самое неприятное то, что с точки зрения реализации передача параметра по имени означала не макроподстановку (иначе теряется смысл процедур, т.к. это слишком накладно). Разработчики компиляторов использовали следующий прием. В случае, когда параметр передавался по имени, при обращении к соответствующему параметру, компилятор подставлял не адрес, как это было при передаче параметра по ссылке, а процедуру вычисления адреса. thunk - это маленькая процедура, которая выдавала значение адреса соответствующей переменной. В случае, если фактический параметр – простая переменная, thunk просто возвращал значение адреса этой переменной. В случае, если фактическим параметром являлся элемент массива (или что-то, что могло поменять свое значение), thunk перевычислял значение соответствующего внутреннего выражения (а оно могло быть достаточно сложным), и далее вычислял адрес соответствующего элемента массива. Обращение к thunk производится в любом случае вне зависимости от того простой параметр или сложный, т.к. в этот момент мы ничего не знаем о фактических параметрах. Например, в процедуре Swap он вычисляется 4 раза. Поскольку процедура широко используется в любой программе в любом ЯП, язык весьма неэффективен. Передача параметров по имени – одна из главных причин неэффективности Алгола 60.

  Этот механизм передачи параметров не подходит императивным ЯП. Им подходят механизмы передачи параметров по значению и по ссылке. Передача по ссылке более универсальна для императивных языков. А  динамическим ЯП способ передачи параметров по имени очень подходит. Т.е. он подходит там, где нет явного понятия состояния памяти. Способ передачи параметров по имени дает возможность организовать так называемые ленивые вычисления. Это вычисления, в которых выражение вычисляется только тогда, когда требуется его значение. В императивных ЯП ленивые вычисления используются при вычислении логических выражений.

a & b & c

Если значение а равно 0, то значения выражений b и с в большинстве ЯП (например в С и С++) вычисляться не будут. Они будут вычислены только в том случае, когда нужны их значения. Если а=0, вся конъюнкция равна 0, b и с вычисляться не будут.

  В динамических языках (это в основном функциональные языки) в случае передачи параметров по имени используются ленивые вычисления.

f(a, b, c)

Когда функции потребуется аргумент b, будет вычислено значение фактического параметра. Если он не нужен, то этот фактический параметр вычисляться не будет вообще.

   Ключевые параметры.

  В ряде ЯП есть способ передачи параметров с помощью ключевых слов. Например в языке Ада

procedure P(X: integer := 0, Y: integer := 0);

В Аде можно задавать значения параметров по умолчанию.

К Р можно обращаться

Р(1, 2);

P(X=>1, Y=>2);

P(Y=>2, X=>1);

Допустима почти любая комбинация. Например:

Лекция "Ввод газопровода в помещение" также может быть Вам полезна.

P(1, Y=>2);

Способ

P(Y=>2, 1);

не допустим, компилятор не понимает, что такое 1.

  Т.е. при ключевом способе задания параметров эти параметры могут передаваться в любом порядке. Но если один параметр стал ключевым, то все последующие тоже должны быть ключевыми. Ключевой способ передачи параметров хорош тем, что программа становится более документированной. Он особенно удобен, если у нас есть значение по умолчанию. Например, когда у нас 10 параметров, а нам нужно задать всего 2, а все остальные по умолчанию, причем эти параметры находятся посередине, можно указать по имени только те значения, которые отличны от значения по умолчанию. В книге Страуструпа "Дизайн и проектирование языка С++" описывается хорошо аргументированное и документированное предложение от фирмы Microsoft по включению в язык С++ ключевых параметров. Параметры по умолчанию в С++ есть, значит ключевые параметры были бы кстати. Это предложение было отвергнуто комитетом по стандартизации языка С++ потому, что оно ничего не дает с точки зрения удобства программирования.

  Из всех языков, которые мы рассматриваем, только в Аде есть ключевые параметры.

Свежие статьи
Популярно сейчас
А знаете ли Вы, что из года в год задания практически не меняются? Математика, преподаваемая в учебных заведениях, никак не менялась минимум 30 лет. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Нашёл ошибку?
Или хочешь предложить что-то улучшить на этой странице? Напиши об этом и получи бонус!
Бонус рассчитывается индивидуально в каждом случае и может быть в виде баллов или бесплатной услуги от студизбы.
Предложить исправление
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5076
Авторов
на СтудИзбе
455
Средний доход
с одного платного файла
Обучение Подробнее