Лекция 3 (Лекции (2009) (Саша Федорова))
Описание файла
Файл "Лекция 3" внутри архива находится в папке "Лекции (2009) (Саша Федорова)". Документ из архива "Лекции (2009) (Саша Федорова)", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Онлайн просмотр документа "Лекция 3"
Текст из документа "Лекция 3"
11
Лекция 3
Основные концепции инперативных. ЯП – обобщение.
Традиционые Фон-неймановские концепции программирования.
С точки зрения парадигм программирования, выделяют
1- императивное
2-функциональное
3-логическое программирование.
Практически все современные ЯП используют Обьектно-ориентированную парадигму, которая тоже основана на парадигме императивного программирования. Правильнее называть их обьектно-процедурными.
С точки зрени производительности господствующими являются императивные ЯП.
Функциональные ЯП
Примеры функциональных ЯП – чистый ЛИСП(создан в 1961 году), Пролог(1971год), Диалог.
Однако же, несмотря на десятки лет, господствовала имеперативная парадигма программирования.
Можно рассматривать операции как абстракцию ЦП, а операторы – как связь между памятью и ЦП
(Бекус – «отец» Фортрана, в честь него названа БНФ. 1978 год – 31 год назад. Будем ссылаться на лауреатов Тюригнговской премии.
Никлаус Вирт, Джон Бекус – лауреаты Тюринговской премии.
От лауреатов данной премии всегда ждали уникальные Тюринговские лекции.
Одна из этих лекций была посвящена вопросу: может ли программирование обойтись без императивного пути развития? Функциональное программирование становится более известным в определенных кругах.). Почему же императивное программировнаие не дает развиваться ллогическому? Дело в том , что реализация его намного эффективнее, чем у функционального, и уж тем более, у логического программирования.
Может ли ситуация поменяться в будущем? Да: именно сейчас развитие аппаратуры привело к тому, что простое увеличение производительности уже исчерпано.
Пример. Самый «крутой» процессор: Pentium Extreme Edition: 4ГГц+ переносной холодильник .
Таким образом, изические ограничения вынуждают программистов рассматривать альтернативные парадигмы, возвращаясь к функциональному программированию.
Императивные ЯП основаны на последовательности. Надо их распараллелить, а именно распараллеливание проще производить при помощи функциональных ЯП.
Но пока императиыне ЯП все же преобладают над остальными.
Базисные понятия ЯП(общая «характеристика» для всех ЯП)
Пункт 1. Данные, операции, связывание.
Данные в императивном ЯП являются абстракцией ОП. Что это? Сущность, над которой можно выполнять некоторые операции(операции – то что можно выполнять над данными ). Этот замкутый круг не случаен.
Любой ЯП определяет понятия данных и операций. Между данными и операциями существует определенный дуализм.
Пример
Возьмем понятие «строка». Что есть длина строки? Это данные или операция? Строки в Си, как и во многих других раочих ЯП, хранятся как последоватеьность символов, заканчивающихся нулем. Следовательно, чтобы узнать длину, нам потребуется пробежаться по всему массиву.
s: string
length: byte absolute 5
Данная запись означает, что байт lenht и строка s начинаются с одного и того же байта памяти.
BSTR (Basic String). В таких строках длина указана явным образом.
Дуализм данных и операций выражается в понятии свойств(если мы говорим в терминах ОО ЯП, в терминах геттеро и сеттеров- Delphi, C#) В языках, где свойств нет, реализованы их аналоги.
Свойство
Int x{
get{…}
set{…}
}//С точки зрения ЯП, это свойство.
С точки зрения его употребления, свойство – это данные, представляющие собой целочисленную переменную.
С точки зрения реализации – это последовательность операций в функциональных блоках.
Итак, понятие свойства:
С точки зрения идеи – данные
С точки зрения реализации – понятие процедуры.
(Дополнительную гибкость придает то, что свойство доступно только на чтение либо только на запись.). Свойство неплохо иллюстрирует доступ к данным и операциям.
Что же главнее с точки зрения современных концепций?
Вспомним основы ООП: там при проектировании класса говорилось об инкапусляции(все поля были либо private либо protected). => интерфейс – функциональный, а данные – средство его реализации.
Поля мы грамотно открывать лишь в тех ЯП, которые поддерживают понятие «свойств».
О связывании
Вопрос необходимости связывания
На его важность вперые оброатил внимание Терн Траер. Самым важным является не проянение понятие взаимосвязи но и также обьекта данных(ОД)- понятие константы. В любом ЯП присутствует понятие значения. Существует некоторая связь между обьектом и его значением. В любом обьекте данных низкоуровневые атрибуты связаны.
Пример: x.f();//связь между именем функции и ее телом.
-
имеют смысл различные виды связывания.
Время связывания(не путать с моментом связывания!)
Существует два основных интервала связывания:
-до начала работы программы(статическое связывание)
-во время работы программы(динамическое связывание)
Мы будем придеоживаться более тонкой классификации.
Пример
C:integer //связывание происходит ДО начала работы программы
Нас в основном будет интересовать статическое связывание
На этапах:
-компиляции
-трансляции
-линковки(сборки)
(С точки зрения ЯП связывание на этапе трансляции является статическим.)
Во время работы программы существует 2 вида связывание: динамическое(между обьектом данных и его значением, момент выполнения оператора присваивания) и квазистатическое.
Вопрос: какое связывание у константы: статическое или динамическое?:
Пример(Паскаль)
Const N=20;//выполняется статически транслятором при генерации соответствующего кода(загрудчик)
С++ требует, чтобы все возможные операции над константами выполнялись при трансляции, это входит в стандарт языка.
Void f(int N)
{
k=N;//происходит во время выполнения, но похожа на статическую реаизацию
}
Еще пример.
Integer const i=20; //допустимо с точки зрения языка АДА, но должно быть именно const
Или:
Procedure P(L: integer)
{
k: integer const=L;//а здесь const быть не обязано! Оно вычисляется в момент входа в соответствующий блок. Такое связывание похоже на статическое, но выполняется оно во время работы программы.
}
Итак, нас интересуют разные виды связывания и, болеее всего, время связывания.Мы выяснили, что существует динамическое, статическое и квазистатическое связывания.
Пример. Виртуальные фнукции: если вызов происходит через ссылку или указатель, связывание динамическое, иначе – статическое.
Императивные ЯП
Любой обьект данных связан с некоторыми атрибутами:
-
имя(характеризуется идентификатором)
-
значение
-
адрес
-
тип данных
-
время жизни
-
область видимости
-
область действия
НЕ все эти атрибуты являются обязательными.
Пример.
int a[10];//Каково имя второго лемента массива?
Int i=2; a[2]<->a[i]-результат вычисления некоторой операции – индексирования. Речь в данном случае идет о применении к массиву данной операции.
Вывод: Имя, как и значение – необязательный атрибут.
Еще пример.
X* p=new X();
X & x=*p;
//&x – вполне можно брать
delete(&x);
Адрес от ссылки брать можно, а от константы – нельзя, так как у нее нет совего адреса.
Ключевой момент для нас тут – не сами понятия, а связывания, которые соотносятся с этими понятиями. Для константы, как мы выяснили, связывание статическое, а для переменных – динамическое.
ИМЯ, ЗНАЧЕНИЕ, АДРЕС И ТИП ДАННЫХ
Как обьект даных связывается с атрибутом «имя»? Это происходит, очевидно, в момент обьявления. Данный вид связывания настолько важен, что в некоторых ЯП он характеризуется особой конструкцией. Это статическое связывание.
Что является решащим в определении типа данных? Чем он выделяется, по какому признаку мы приписываем обьекту его тип данных?
1969 год – Никлаус Вирт одновременно с созданием языка Паскаль пишет книгу, в которой утверждает, что тип данных определяется множеством значений. Вскоре осознается порочность этой точки зрения.=> статья «Тип данных – не значение», с точки зрения которой тип данных явлется множестовм операций.
Итог(господствующая точка зрения):
Тип данных=множество значений+множество операций
Пример
Представим себе структуру:
Если точно описать набор соответствующих операций, можно догадаться, что это стек. Реализован он то ли в виде массива, то ли в виде линейного списка. Форма реализации становится важной тогда, когда мы занимаемся оптимизацией. (Использовать линейный список значительно эффективнее)
С современной точки зрения важно именно множество операций, и как мыы знаем, хороший подход к проектированию членов класса заключается в том, что публично лишь множество операций(основное, что есть у типа данных)
Создавая абстрактный тип данных, мы абстрагируемся именно от множества значений, уделяя основное внимание именно множеству операций. Концептуально абстрактный тип данных – вещь гораздо более мощная и более важная, чем все остальное(классы, полиморфизм и т.д.).
Когда происходит связывание обьекта с его типом данных? Большинству ЯП присуща статическая типизация. Однако в некоторых ЯП (интерпретирующие ЯП – JavaScript, Php) разрешено менять тип данных некоторых переменных.
2 основных недостатка такого вида типизации:
1)Меньшая эффективность. Когда типизация статическая, компилятор может многое прогнозировать – ЯП со статической типизацией более эффективны
Если метод невиртуальный и функция статическая, что операций типа x.f(); надо делать гораздо больше(залезть в таблицу имен, по ней найти функцию, выполнить операцию «.», а уж затем произвести вызов функции).
Таким образом, производительность таких ЯП оставляет желать лучшего.
Замечание . Тем не менее, большенство серверов, для которых эффективность – одно из глафных требований, пишутся именно на интерпретирующих ЯП: создавать программы на таких ЯП легче и удобнее.
2) Меньшая надежность.При интерпретации компилятор может не заметить отклонение, которое вылезет потом, что ставит под угрозу надежность web-сайтов..
(Впрочем, некоторым сайтам излишняя надежность вредна)
Как мы знаем, ЯП бывают традиионные и обьектно –ориентированные(надстройка ООЯП). Чем отличается даннная надстройка от традиционных ЯП?
Пример классического традиционного ЯП: Ада(стандарт 1983 года). В чем отличие ее от С++?
Отличие между этими двумя ЯП состоит именно в типизации. В традиционных ЯП любой обьект данных принадлежит одному и только одному типу данных, который определяется при трансляции. В обьектно-ориентированных ЯП обьект данных может принадлежать сразу нескольким типам данных: производному и базовому классам. (derived, based). Собственно обьекты классов обладают динамической типизацией: указатель на базовый класс. Динамический тип – это тип обьекта даных в настоящий момент. Важно, что в ООЯП тип данных у обьекта уже не единственен.
А в традиционных ЯП все Типы Данных распадаются на традиционные непересекающиеся классы эквивалентности.
ВРЕМЯ ЖИЗНИ
Время жизни обьекта данных зависит от момента размещения обьекта в памяти до его ухода из памяти.
-
Все время работы программы(глобальное, статическое)- «добрый старый» С, который по умолчанию делает все обьекты статическими
-
Динамическое(см ниже)
Часто время жизни обьекта связыва.т с понятием «класса памяти»(ОО ЯП)
Время жизни в таком случае определяется самим программистом – для этого он использует операторы new и delete. (dispose в Паскаль).
В некоторых ЯП время окончания жизни любого обьекта определяется «Сборщиком мусора»(динамиче6ская сборка мусора – система времени выполнения).
Существует также так называемый промежуточный тип – обекты внутри блоков(автоматический класс памяти+автоматический обьект):блок набора обьявлений+набор операторов.
Время жизни локальных обьектов: вход в блок – вызод из блока(то есть время жизни=время работы блока).
В зависимости от времени связывания обьект будет статическим либо динамическим(в сучае квазистатического связывания – квазистатическим – когда обьект автоматически уничтожается по выходу из блока)