For most languages, it is characteristic that a programmer can (and should!) Think of program execution as an automaton with an active processor and passive memory (possibly heterogeneous) connected by a channel . The appearance in the language of data structures and the so-called high-level constructions, as well as the possibility of using libraries, is just an increase in the level of the abstract calculator of the language, which, nevertheless, is treated as an automaton of the traditional type, even with very complex commands. If the language does not correspond to this idea of the program, then we call this language non-traditional . The degree of rejection of such a presentation can serve as an assessment of the degree of non-traditionalism.
From this point of view, such modern languages as C ++, Ada or Java remain traditional, although in the order of enumeration their traditionality is reduced, and, for example, such "ancient" languages as LISP, Refal and Prolog are unconventional.
Consider the traditional languages , the key means of which "grew" from the traditional architecture of machines. The following are the language features inherited from this architecture.
Operator The basic construct that expresses actions is the operator. The execution of one statement depends on the execution of the other only in the sense that earlier calculations can change memory.
The assignment of values is the most common type of statement. In most programming languages, the concept of a variable is considered as an analogue of a cell (or group of cells) of memory. Assignment is intended for local storage of the result of calculations. It is a direct descendant of transmitting a value over a communication channel from the processor to the memory.
Management structure Unless explicitly stated otherwise, the statements are executed textually one after the other. This corresponds to the sequential execution of instructions by the processor. The transition operator is treated as an explicit indication of the operator that should be executed next. It corresponds to the machine command unconditional transfer of control at. The same can be said about situations when calculations determine which operator will be executed next (conditional operators, cycles, etc.). The prototype of these operators were frequently used programming techniques in the command language.
Cast In traditional languages, it is common to use a value of one type, which is assigned to a variable of another type. The automatic casting of generated values to types determined by the context of use is a direct consequence of the agreement on memory uniformity. In developed programming languages (except family C), they try to avoid uncontrolled casts 1 .
A subroutine is a group of statements that has its own name. Such a sequence can be accessed repeatedly. Subroutines appeared in machine languages as well, since they are necessary for accumulating programmer knowledge and facilitating work with complex programs. A feature of the subroutines is that their description is separated from the call operator of the subroutine, and after the call operator is executed, control returns to the same context as before the call, and control is transferred to the operator immediately following the call.
Note that in sufficiently developed languages, the programmer builds the texts of programs in accordance with the peculiarities of the problem being solved, moving away from those rules that are clearly supported by the language (write in a different style). But if the language lacks adequate capabilities for such a construction (and this is, generally speaking, a common situation), then you have to resort to hacking 2 modeling the necessary capabilities. When high efficiency is required (and this, again, usually) the realities of a particular computer must be taken into account. As a result, a violation of the modeling adequacy and a loss of clarity of the solution are very likely.
We give with a few comments far from a complete list of traditional languages.
1. FORTRAN . Patriarch among programming languages, gradually incorporating new trends, but fully preserving continuity in its best and worst sense. Today FORTRAN is an eclectic collection of both useful and archaic means. Referring to FORTRAN, we mean the language formed in the mid-seventies, the so-called FORTRAN-77 (further modifications are not so important). The FORTRAN computational model corresponds exactly to the idea of what is needed to implement computational algorithms and what can be implemented on traditional computers of the type created in the 1950s. XX century. Thus, it is the most consistent example of a traditional language.
Developers of earlier versions of FORTRAN did not take into account the usefulness of defining a language independent of the programming system. And the formal definition of a language was essentially a translator. As a result, random decisions made in the early translators, subsequent developers are forced to save for many years. For this language, this state of affairs is explicable and excusable. 3
FORTRAN is a classic example of a language with a static definition of memory: even at the translation stage, it is precisely determined where everything lies.
2. Algol 60 . A language formed as a realization of the idea of the representation of algorithms that is simultaneously understandable both for computers and for humans. Very soon, the utopian idea became clear, and Algol 60 4 became, in the eyes of programmers, practitioners 5 only more strict, but more verbose, less familiar and effective analogue of the FORTRAN language. In fact, fundamental innovations appeared in Algol, which distinguish it favorably from its predecessor. This is, first of all, the definition of a language, independent of the translator, further, the structural description of the language and the definition of the actions of an abstract calculator based on concepts from a strict description of the language.
In Algol, for the first time, a structural organization of construction execution contexts was proposed, which takes the language calculator beyond the canon of homogeneity and direct arbitrary indexed addressing of memory, the so-called block structure of the program . Thus, the stack discipline of memory allocation in work programs was invented. With such a memory allocation, space for the concepts described in a block is allocated at the entrance to the block and is released after its completion.
The stack discipline has since been widely used in the implementation of programming languages.
Although the concept of structured programming has not yet been realized, Algol 60 has the entire necessary base for it.
It is no coincidence that Algol became the starting point for the development of most programming languages, as well as the basis of many theoretical developments that clarified linguistic and programmer concepts. Before the era of personal computers, computing architectures that clearly support Algol's memory organization appeared. The most famous of these are the machines of the company Burroughs (USA) and the line of multiprocessor computing complexes Elbrus (USSR).
Thus, Algol 60 was a significant step forward, and in terms of conceptual unity, it still remains unsurpassed among traditional languages.
3. Simula 67 is characterized by developers as a universal modeling language. This, like its predecessor, Simula 1, is the correct extension of Algol 60, and therefore preserves its strengths and weaknesses. However, it was precisely the shortcomings of this base that became the main reason why these languages were undervalued by practitioners. The developers of Sims 67 showed how to express programmer experience in linguistic forms: implement not specific solutions, but informative entities that generalize them. As a result, new constructions for that time, reflecting an object view of the processed data, became the basis for promising programming methodologies, in particular, for an object-oriented programming methodology.
4. PL / 1 . This language was developed as an attempt to merge everything that a programmer might need in principle. It is not known whether this is so or not, but it is quite plausible that the number “1” in the name of the language is an ambitious “one”, that is, it can make any other programming language meaningless. Without worrying about the cleanliness of combining all known programmer tools, the language developers proposed an initially eclectic collection, which can only be called a system with a stretch. The unknowability of the language is noted by many critics. In the words of E. Dijkstra, PL / 1 is a “Christmas tree” and not an instrument that can be used effectively. Fragmentation and irreducibility to single concepts creates great difficulties for implementation: the programming systems for PL / 1 always distinguished a certain dialect, essentially defining a corresponding subset of means depending on the translator.
5. Algol 68 is a programming language that, like PL / 1, claimed to be universal, but on the basis of mathematical generalization of disparate programming tools in the traditional model of computation. It can be said that it is PL / 1 with elements of science (S. Koster). The attempt to distribute funds that have proven themselves in one area to the level of maximum generalization was generally successful, but the developers recorded in language forms only what was already known at the time the language project appeared. For this reason, in Algol 68 there are no good means of supporting the modular construction of programs; in exact accordance with the traditional architecture, the processed data is not active. The disadvantages of the language include a ponderous formal description, completely inaccessible for practical use as a guide for the programmer 6 . The main merit of the developers of Algol 68 is that they managed to put into practice the principle of lossless generalization, demonstrated the productivity of this principle. The presence in this course of references to the language Algol 68, which is actually not used now, is explained by the fact that in this language, despite obvious flaws in the form of language description, there were at the same time a number of brilliant conceptually important findings, such as the conceptual system that remains to this day of the most consistent and strict. Some of the concepts of Algol 68 were perceived in the languages of C and Ada, but the system itself was lost. Until now, the magazine " Communications of the ACM " periodically contains comments on published articles, titled approximately in the following style: "Algol 68 ignorance is considered harmful", which boils down to the fact that the next "new" proposals are only a worsened version of what is already It has long been implemented in Algol 68.
One of the motivations for creating a language was the awareness of a coherent concept of a type system, calculated statically, that is, during a program broadcast.
The basic machine allows arbitrary interpretation of the meaning of stored values (the principle of homogeneity of memory), but for humans, the meaning of the values is primary, so the program needs to fix not only the calculations, but also the types of values. There is a possibility of semantic control of the program, which is separated from data processing. To do this, you need to strictly define the types and give exact mechanisms for constructing some types through others. Such a definition allows, without knowing the specific values of the variables included in the expression, to determine the type of expression. As a result, a number of substantial potential errors in the program can be identified already during the broadcast. But in Algol 68, this concept was not well implemented.
6. Pascal is one of the most common programming languages. For this reason, it is represented by many dialects and versions. The first Pascal was proposed by N. Wirth in response to a fundamental disagreement with the position of the leadership of the working group on the creation of Algol 68, in particular with van Weingaarden. The main criticism of Wirth is the excessive complexity of the language and especially the method of its formal description.
In particular, Pascal gave a more elegant and programmatic implementation of the idea of a static type system, which arose at a time when the initial Algol working group 68 did not fall apart 7 .
There are other features of the Pascal language that make this language strict, and there are natural limitations of possibilities that simplify the understanding of language tools by the programmer. The language is designed to support the writing of good programs (in the understanding that developed by the end of the sixties). All this made it possible to assert Virtue that he developed a language for teaching students programming. This statement is not without reason, especially if we bear in mind that there is a method of teaching with its help, which was developed by Wirth himself. In educational institutions where there are serious computer science courses, Pascal remains the most common language of instruction.
Shortly after its appearance Pascal becomes a popular programming language. But programming continued to evolve, new concepts appeared. Wirth himself develops heir-based languages based on the Pascal language, which to a large extent support programming with independent modules: Modula and Modula-2.
Closer relatives of the standard Pascal language also deserve attention, consistently version by version suggested by the Borland team: languages and programming systems of the Turbo Pascal line. In them, new, highly developed capabilities organically fit into the system of the parent language, without violating the concepts. Unfortunately, in the Delphi system developed by the same company, Object Pascal falls out of this series: it was not possible to preserve conceptual integrity.
7. C language and other machine-oriented languages . The realization that programming with the use of a universal language, which does not reflect the characteristics of specific computing equipment, does not make it possible to achieve the maximum efficiency of programs on this equipment, has led to the emergence of so-called machine-oriented languages . The popularity of such languages depends not only on the prevalence of the equipment for which they are designed, but also on the success of the projects carried out with their help.
In this respect, language C is indicative, the success of which was largely ensured by the successful solution of the Unix operating system. For the development of this system on the PDP series machines, the C language was built, with the help of which, in particular, a technologically advanced software transfer method was proposed. For the sake of fairness, it should be said that although the contribution of the Unix system to C's success is very large, it is equally important that this language provides a shell that is quite convenient for composing effective programs that covers inexpressive machine-level tools. The growing popularity of this language influenced the fact that computers began to be designed so that their architecture corresponded to the C computation model of the language. As a result, the popularity of such architectures grew. In this process, the most successful company is Intel, whose processors are becoming the de facto standard in the development of personal computers. Today it is no longer possible to imagine a mass computer that would not support software developed for these processors 8 .
The C language is, if not the first, then one of the first programming languages in which, from the very beginning of its existence, the idea to consider as a calculator not the command level of a particular computer, but the level of the operating system was proclaimed. In other words, there are constructions in this language, the execution of which cannot be carried out without a corresponding reference to the means of the operating system. Of course, this is not an innovation. In all practically used programming languages such tools exist, and they always expand the programmer's view on the environment of the program. But most often they are represented in the language as subordinate means, brought to the level of libraries, and they are far from always exactly specified. In C, the situation is different. In particular, along with automatic memory allocation, the language defines the mechanisms for allocating memory plots by requests and returning them when they are no longer needed.
Against the background of the well-deserved popularity of C, it is appropriate to mention the less common language Bliss. This machine-oriented programming language could be a conceptually more verified alternative to C, but the lack of a project developed with its help, comparable in significance to Unix, did not allow it to stand out. Although, ideologically, Bliss influenced language creation, interest in it did not extend beyond academic studies.
Domestic experience in developing computer-oriented languages demonstrates support for an architecture other than Intel-like. We point out two projects of this kind. The first one is the YARMO language (abbreviation: the machine-oriented implementation language ), built for the BESM-6 computer and reflecting all the trends in computer science at that time.The quality and relevance of this language can be judged if only because several of its versions have been implemented. The second example is the El-76, developed as an analogue of the assembler language for the Elbrus multiprocessor computer complex. Remaining on the whole a traditional machine, the architecture of this complex is far enough away from the canonical principles. In particular, it provides hardware support for procedure calls, stack-based memory organization, tagging, and other high-level programming tools.
All the architectural features of Elbrus are reflected in the El-76, which made it possible to consider this language as the only tool for programming system programs. Of course, it is impossible to talk about the mechanical transfer of this language to an architectural environment of another type, and therefore the time it is used, like any computer-oriented language, is limited to the lifetime of this architecture 9 .
8. Ada language . Он разрабатывался по заказу Министерства обороны США на конкурсной основе с предварительным сбором и анализом требований, с обширной международной экспертизой. По существу, в нем воплощена попытка определить язык программирования как экспертно обоснованный комплекс средств программирования. На завершающем этапе конкурса приняли участие около ста коллективов. В результате проверки на соответствие представленных разработок сформулированным требованиям для обсуждения общественности было отобрано четыре языка, зашифрованных как Red, Green, Blue и Yellow. В разной степени критике подверглись все четыре кандидата. Особенно острым критиком оказался Э. Дейкстра, который камня на камне не оставил от Red, Blue и Yellow, но чуть-чуть "пожалел" Green, доказывая, что все недостатки языка связаны с несвободой в выборе решений, обусловленных жестко фиксированными требованиями: там, где авторы могли бы решать какие-либо проблемы по-своему, они были вынуждены идти на поводу у априорных предписаний. Тем не менееGreen стал приемлемым вариантом и получил одобрение. Как оказалось, это был единственный из финалистов язык, предложенный не американцами. Конкурсная комиссия утвердила его в качестве единого официального языка Министерства обороны США для разработки программ для встроенных систем и дала ему имя Ada — в честь Ады Августы Лавлейс, дочери Байрона и ученицы Бэббиджа — первой в истории программистки.
Отметим, что успеха разработчики языка добились благодаря акценту на концептуальную целостность — именно это выделяло Green среди конкурентов. Заметим, что в ходе последующего развития в язык Ada стали включать новые средства в угоду появившимся пользователям. В результате к концу девяностых годов Ada по стилю построения стала подобна PL/1: в ней есть средства поддержки всего, что можно найти в работе программистов в конце XX века. Как отмечал известный советский программист В. Ш. Кауфман, язык Ada 9х можно рассматривать как добротную энциклопедию программистского знания и опыта, но никак не в качестве инструмента, ориентированного на пользователя.
9. Объектно-ориентированные языки. The latest achievement in the field of programmer language creation is the support of object-oriented methodology. This field interests many language developers since the eighties. The first project that proclaimed the principle of transition from passive data to active objects was Smalltalk. In this language, objects are given the opportunity to act in response to the messages they receive without any other means of activating actions. This feature is implemented within the framework of the idea of dynamic typing (in contrast to static typing, the type of expression can be calculated within certain limits along with its value). As a visual demonstration of the power of the idea, a Smalltalk-80 programming system was proposed with a very rich library support for constructing graphical interfaces.
Smalltalk is the last major project that was presented for in-depth discussion by the programmer community. As a result of such discussions, it became clear that it was necessary to support object orientation in the languages of industrial production of programs. Such languages appeared soon enough.
Turbo Pascal versions from 5.5 to 7.0 and Object Pascal of the Delphi system have become notable object languages.
Common to the industrial development of the Smalltalk language line is a return to static data types, heightened attention to security issues. There are programming systems that are acceptable for the efficiency of the object code and satisfy the requirements of high-tech programming. However, as is usually the case with production systems, an analytical study of the limits of applicability and the role of language has been replaced by an advertisement of merits and silencing flaws.
10. C ++ language . The most common object-oriented language received C ++, apparently because of the huge popularity of C.
C++ был создан в конце 80-х гг., он практически являлся расширением C. В отличие от языков семейства Simula, в С++ воплощались не столько концепции, сколько конкретные, полезные для его создателей, приемы. Язык С++ по конструкции намного сложнее С, аопределение его производит впечатление еще большей эклектичности. Но С++, усугубив недостатки С с точки зрения человека, сохранил при колоссальном расширении возможностей языка все достоинства С, касающиеся машинной ориентированности и эффективности.
С++ отличается прежде всего значительным усилением системы описаний (объектно-ориентированные возможности являются одним из наиболее применяемых расширений) 10 .
Еще более укрепляют позиции языка С++ многие современные инструментальные системы, создававшиеся на нем без учета потребностей других языковых средств. В частности, системы работы с динамически подключаемыми программами ( middleware ) CORBA и COMпрактически требуют, чтобы программа, к ним обращающаяся, была написана на С++, поскольку вся система интерфейсов ориентирована на типы данных этого языка и порою даже на конкретные их представления.
11. Язык Java . Заметным этапом в развитии объектно-ориентированного подхода стало появление языка Java, который был предложен как средство программирования не для отдельного компьютера, а сразу для всех машин, имеющих реализацию так называемой Java -машины — исполнителя программ на промежуточном языке более высокого уровня, нежели командный язык обычных машин. Иными словами, реализуется система программирования с явно определенным промежуточным языком. Другая особенность Java -проекта — его ориентация на Интернет-программирование: поддерживается возможность построения приложений, работающих сразу на нескольких машинах.
Схема трансляции с выделенным промежуточным языком, не зависящим от исходного языка, не нова. В шестидесятые годы ее пытались применять для сокращения расходов на разработку трансляторов (например, в США в качестве промежуточного языка был разработан язык Uncol, в Советском Союзе для тех же целей предлагался язык АЛМО).
Пусть требуется реализация m языков на n машинах. В схеме без промежуточного языка в этом случае нужно запрограммировать mx nтрансляторов, тогда как использование такого языка позволяет сократить это число до m + n: для каждого языка пишется транслятор впромежуточный язык ( m ) и для каждой машины создается транслятор или интерпретатор промежуточного языка ( n ). Можно предположить, что затраты на 'половинки' трансляторов сократятся. Схема может быть реализована, если удается построитьпромежуточный язык, удовлетворяющий следующим условиям:
Выполнить эти условия весьма сложно даже для близких языков и машин, близких по архитектуре. Затраты на решение этих задач часто неизмеримо и неоправданно превышают стоимость пресловутых mxn трансляторов, поэтому после серии экспериментальных проектов идея промежуточного языка была предана забвению. В проекте Java она возродилась (правда, в урезанном до одного языка варианте) благодаря почти унифицированной архитектуре массовых компьютеров и значительному росту технических возможностей машин.
It is these additional conditions, as well as the qualified narrowing of the C ++ source language, that allowed to implement the old idea in industrial development 11 .
In the context of the discussion of traditional languages, it is necessary to consider how far the Java language and the Java-machine deviate from the traditional model of computing. The joint development of these two components of the programming system for a new language made it possible to come up with quite practical trade-offs, to satisfy the conditions of the chosen implementation scheme, which was discussed above.
Condition (1) is performed almost automatically, and one can focus on ensuring the most rational embedding of the model of language calculations into the model of the machine. As for condition (2), here the stake was placed on the actual similarity of the architecture of specific calculators, for which experience in programming solutions has already been accumulated in many typical situations. As a result, the departure from the traditional model of computing in the Java-system, although noticeable, is not so significant. Suffice it to say that the Java machine is built on the principles proposed as far back as 1963 for organizing the calculations in the working program of the Whetstone compiler for Algol 60 12 .
An important new quality of the Java-machine is the support of the work of a programmer with potentially unlimited memory. When running a specific program in Java, you can not worry about the fact that some part of the memory is no longer necessary. The programming system itself will make so that the memory that was inaccessible, and therefore unnecessary, is returned for use in new requests. Such situations are revealed in the calculation process, when the actual resources provided for data placement need to be replenished for reuse. For the sake of this agreement, they abandoned a number of methods of organizing manual reuse of memory, which are necessary, for example, when programming in C.
The Java computing model corresponds exactly to what is required of object-oriented programming: memory activity at the object method level, a joint description of the data and program methods, the separation of the provided tools from their implementation. All this is combined with the traditional scheme of computing management in the description of processing algorithms.
It should be noted that the developers of the language did not include in it the means that hardly fit into the conceptual scheme of the Java-machine and are usually provided through fairly arbitrary implementation agreements (as, for example, in C ++). The orientation of the Java-machine on the classical computational organization since Algol 60 influenced the language in the sense that everything beyond the accepted model is presented in such a way that it can be calculated during the broadcast period. For example, the problems of static typing in this language are solved radically: there are simply no means for constructing structural types that are different from classes of objects. As a result, the language became more concise, for example, compared to C ++.
For the first experience, Java harmoniously combined a number of innovations that appeared in separate languages in various languages, and which, in aggregate, raise the level of initial concepts to approximately the second type in the type hierarchy. Java programming fundamentally departs from the focus on the features of specific solvers. It remains only to assume (not always justified!) That the machines used perform the required actions with an acceptable level of efficiency.
To a large extent, in order to seize the initiative from the Java language, C # was created, which effectively works primarily with middleware systems, and strives to preserve the effectiveness of C / C ++ in a new field. For our purposes, in most cases, the differences between C ++ and C # are not significant.
As you can see, traditional languages have gone the way of serious evolution. Let's see how traditional principles of computing are transformed when using an object model. Obviously, the departure from the uniformity of memory for this model is more radical than, for example, in the Pascal language. If we consider objects as data stored in memory, then due to the connectedness of this data with programs (methods of objects), the memory in the object model becomes active. At the conceptual level of consideration, you can see that management is being modernized: the object itself knows which program method needs to be activated in order to perform an action. Undoubtedly, all this increases the flexibility of programming, contributes to the expansion of the possibility of departing from the traditional view of the program as an automatic machine that fulfills the instructions-commands. However, at the level of implementation of program-methods, everything remains the same: the same sequential execution of statements, the same approaches to the branching of calculations and to the organization of cyclic processing.
Moreover, the sequential nature of the calculations remains with the definition of the interaction of objects. Consequently, the object approach, although it contributes to the view of computational processes, which differs from the traditional style, does not in itself lead to a change in the basic model of computation.
Object-oriented approach is currently used to organize calculations based on models other than the traditional ones. At the same time, the conceptual compatibility of the object-oriented approach with the new base and the relative level of the base and the superstructure are not taken into account at all. An example is discussed in the chapter on functional programming.