Сравнение языков программирования
Сравнение языков программирования — соотнесение языков программирования по схожим и различающимся признакам.
Условные обозначения | |
---|---|
+ | Указанная возможность присутствует |
- | Указанная возможность отсутствует |
+/- | Возможность поддерживается не полностью |
-/+ | Возможность поддерживается очень ограниченно |
? | Нет данных |
N/A | Постановка вопроса не применима к языку |
Отмечено наличие или отсутствие тех или иных возможностей в некоторых популярных сегодня языках программирования. Столбцы упорядочены по алфавиту. Если возможность в языке недоступна напрямую, но может быть эмулирована с помощью других средств, то в таблице отмечено, что её нет.
При заполнении таблицы учтены только фактические данные, при том, что наличие возможности не обязательно является преимуществом языка, а отсутствие — недостатком.
Парадигмы[править]
Возможность | Языки | |||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | Prolog | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic | |
Императивная | + | + | + | + | + | + | + | - | - | + | + | + | + | + | + [1] |
+ | + | + | + | + | + | + | + | + | + | + | + | + | + | + |
Объектно-ориентированная | + | + | -/+[2] | + | + | + | + | - | - | + | +/- | + | + | + [3] |
- [4] |
+ | + | + | + | + | + | + | -/+ [5] |
+ | + | + | + | + | + | -/+ |
Функциональная | - | - | +/- [6] | -/+ [7] | +/- | +/- | +/- | + | ? | + | +/- | + | -/+ | +/- | + | +/-[8] | - | + | + | +/- | + | + | + | + | + | + | +/- | -/+ | + | +/- |
Рефлексивная | - | - | - | -/+ [9] | -/+ | -/+ | ? | + | ? | -/+ | - | + | -/+ | + | - | + | - | -/+ | +/- | + | + | + | -/+ [10] |
-/+ | + | + | -/+ | -/+ | - | ? |
Обобщённое программирование | - | + | + [11] | -/+ [12] | + | + | +/- | + | + | + | - | + | + | + | + | + | + | + | + | + | + | + | + | + | + | - | + | + | + | -/+ |
Логическая | - | - | - | - | - | - | - | - | + | - | - | - | - | - | +/- [13] |
+/- [14] |
+ | +/- | - | - | - | - | - | ? | +/- | - | - | - | - | ? |
Декларативная | - | - | - | - | -/+[15] | -/+ | ? | + | + | + | - | + | - | +/- | + | +[16] | - | + | -/+ [17] |
+ | + | + | - | + | +/- | - | +/- | - | + | +/- |
Распределённая | - | + [18] |
+/- [19] |
+/- [19] |
-/+ [20] |
+/- [21] | + | + | - | - | + | -/+ | + | - | + [22] |
+/- | -/+ | - | - | - | -/+ | -/+ | + | ? | +/- | ? | - | - | - | - |
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | Prolog | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic |
Типизация[править]
Возможность | Язык | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic | |
Статическая типизация | + | + | + | + | + | + | + | - | + | + | + | + | - | + | +/-[23] | + | + | +/- [24] |
- | - | - | + | + | +/- [25] |
- | + | + | + | + |
Динамическая типизация | - | - | - | - | + [26] |
- | - | + | -/+[27] | - | + | - | + | -/+ [28] |
+ | + | - | + | + | + | + | -/+ [29] |
- | + | + | + [30] |
-/+ [31] |
- | - |
Явная типизация | + | + | + | + | + | + | + | -/+ [32] |
+ | + | + | + | - | + | +/-[23] | + | + | -/+ [33] |
+/- | +/- [34] |
- | + | + | +/- [35] |
- | + | + | + | + |
Неявная типизация | - | - | - | -/+ | -/+[36] | -/+ | - | + | + | - | + | - | + | + | + | + | + | + | + | + | + | + | + | + | + | + | - | + | + |
Неявное приведение типов без потери данных | -/+ | -/+ [37] |
+ | + | + | + | + | - | - | - | + | + [38] |
+ | - | + | -/+ | + | + | + | + | + | -/+ [39] |
? | + | + | + | + | - | + |
Неявное приведение типов с потерей данных | - | - | + | + | - | + | - | - | - | - | - | - | ? | - | - | - | ? | + [40] |
+ | - | - | - | ? | + | + | + | + | - | -/+ |
Неявное приведение типов в неоднозначных ситуациях | - | - | + | + | + | + | - | - | - | - | - | - | + | - | - | - | + | + [41] |
+ | - | - | - | ? | - | + | + | - | - | -/+ |
Алиасы типов | + | + | + | + | + | + | - | N/A | + | ? | + | - | N/A | + | +[42] | + | + | N/A | N/A | N/A | N/A | + | +[43] | ? | N/A | - | + | + | -/+ |
Вывод типов переменных из инициализатора | - | - | - | +/- [44] |
+ | + | - | N/A | + | ? | - | - | N/A | + | +/- [45] |
+ | + | N/A | N/A | N/A | N/A | + | + | ? | N/A | + | - | + | + |
Вывод типов переменных из использования | - | - | - | +/- [44] |
- | - | - | N/A | + | ? | - | - | N/A | + | +/- [45] |
+ | + | N/A | N/A | N/A | N/A | + | ? | ? | N/A | ? | - | + | +/- |
Вывод типов-аргументов при вызове метода | - | - | - | + | + | + | + | N/A | + | ? | + | + | N/A | + | +/- [45] |
- | + | N/A | N/A | N/A | N/A | + | + | ? | N/A | + | - | + | ? |
Вывод сигнатуры для локальных функций | - | - | - | +/- [46] |
- | ? | - | N/A | + | ? | - | - | N/A | + | +/-[45] | - | + | N/A | ? | N/A | N/A | + | - | ? | N/A | ? | - | + | ? |
Параметрический полиморфизм | - | - | N/A | - | + | + | + | N/A | + | - | + | + | - | + | + | - | + | N/A | + | N/A | N/A | + | + | ? | N/A | + | - | + | ? |
Параметрический полиморфизм с ковариантностью | - | - | N/A | - | +/- [47] |
? | + | N/A | + | - | - | + | - | N/A | + | - | +/- | ? | ? | N/A | N/A | + | + | ? | N/A | - | - | ? | ? |
Параметрический полиморфизм высших порядков | - | - | N/A | - | - | - | ? | N/A | - | - | - | - | - | + | + | - | - | N/A | ? | N/A | N/A | - [48] |
+ | ? | N/A | - | - | ? | ? |
Информация о типах в runtime | + | -/+ [49] |
- | -/+ [50] |
+ | + | + | + | + | ? | + | + | -/+ | - | + | + | + | + | + | + | + | - | + | + | + | + | + | - | - |
Информация о типах-параметрах в runtime | - | - | - | -/+ | + | + | ? | - | + | ? | - | - | -/+ | - | + | + | + | + [51] |
+ | + | + | - | +[52] | ? | - | + | + | - | - |
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic |
Компилятор/интерпретатор[править]
Управление памятью[править]
Возможность | Язык | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic | |
Создание объектов на стеке | + | + | + | + | + | + | -/+ [75] |
? | + | ? | - | - | - | +/- [76] |
+/- [77] |
- | + | - | - | - | - | + | ? | ? | - | - | -/+ [78] |
? | + |
Неуправляемые указатели | + | + | + | + | + | + | - | - | - | ? | - | -[79] | - | -[79] | -[79] | + | + | - | - | - [80] |
- | + [81] |
- | + [82] |
- | - | + | - | + |
Ручное управление памятью | +/- | + | + | + | +[83] | + | - | - | - | ? | - | -[79] | - | -[79] | -[79] | + | + | - | - | -[79] | - | + [81] |
- | + [84] |
- | - | + | - | + |
Сборка мусора | + | -/+ [85] |
- [86] |
-/+ [87] |
+ | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | + | +/- [88] |
+ | + | + | + | - [89] |
+ | - |
Управление потоком вычислений[править]
Возможность | Язык | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | Tcl | VB.NET | Delphi | OCaml | PureBasic | |
Инструкция goto | - | + | + | + | + | + | - | - | N/A | + | - | - [90] |
- | N/A | +[91] | - | + | + | +/- [92] |
- | -/+ [93] |
- | - | -/+ [94] |
- | + | + | - | + |
Инструкции break без метки | + | + | + | + | + | + | - | - | N/A | + | + | + | + | N/A | +[95] | - | + | + | + | + | + | + | - | ? | + | + | + | +/- [96] |
+ |
Инструкция break с меткой | - | + | - | - | - | + | - | - | N/A | ? | + | + | + | N/A | +[97] | - | + | + | +/- [98] |
- | + | + | - | ? | - | + | - | N/A | +/-[99] |
Поддержка try/catch | - | + | - | + | + | + | + [100] |
+ | + | - | + | + | + | + | + [101] |
+ | + | + [102] |
+ | + | + | - [103] |
+ | + | + | + | + | + | +[104] |
Блок finally | + | -/+ [105] |
- | - | + | + | - | - | + | ? | + | + | + [106] |
+ | + [107] |
+ | + | - | + [108] |
+ | + | - [103] |
+ | + | + | + | + | - [109] |
+[104] |
Блок else (исключения) | - | - | - | - | - | - | - | + | - | ? | + | + [110] |
? | + | + [111] |
+ | - | + [112] |
- | + | + | - [103] |
- | ? | + | + | + | + | +[104] |
Перезапуски | +[113] | ? | - | ? | - | ? | ? |
- | - | ? | ? | ? | ? | ? | + |
- | - | - [114] |
? | ? | + [115] |
- [103] |
? | ? | - | - | ? | ? | ? |
Ленивые вычисления | - | ? | - | -/+ | -/+ [116] |
+ | - |
- | +/-[117] | - | - | - | - | + | - [118] |
- | + [119] |
- |
-/+[120] | + | -/+ [121] |
+ | ? | - | - | -/+ [122] |
- | +[123] | + |
Continuations | - | ? | -/+[124] | ? | +[125] | ? | ? |
- | - | ? | ? | ? | ? | + | -[126] |
? | - | ? |
? | - | + | - | ? | + | - | - | ? | +/- [127] |
? |
Легковесные процессы (Coroutines) | + | - | - | - | - | + [128] |
+ | + | - | + | ? | +/- [129] |
- | + | +/-[130] | + | - | + [131] |
+ [108] |
+/- [132] |
+ [133] |
-/+ [134] |
? | + | + | - | - | +/-[135] | - |
Типы и структуры данных[править]
Возможность | Язык | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | VB.NET | Delphi | OCaml | PureBasic | |
Кортежи | - | - | - | +/- | + | +/- | + | + | + | + | + | - | - | + | + | - | + | + | +/- [136] |
+ | + | + | + | + | +/- | - | + | - |
Алгебраические типы данных | - | -/+ [137] |
- | - | - | + | ? | N/A [138] |
+ | +/-[139] | ? | - | N/A [138] |
+ | N/A [138] |
- | + | N/A [138] |
N/A [138] |
N/A [138] |
N/A [138] |
+ | + [140] |
N/A [138] |
- | -/+ [137] |
+ | - |
Многомерные массивы | + | ? | + | + | + | + | ? | - | + | + | + | +/- | +/- | + [141] |
+ | + | + | +/- | +/- | +/- | +/- | + | +/- | ? | + | + | + | + |
Динамические массивы | + | ? | -[142] | + | +/- | + | ? | - | +/- | + | ? | +/-[143] | +/- | - | + | + | ? | +/- | +/- | +/- | +/- | +/- [144] |
+ | ? | + | + | ? | + |
Ассоциативные массивы | - | ? | - | + [145] |
+ | + | ? | - | + | + | + | +/-[146] | + | +[147] | + | - | + | + | + | + | + | + [148] |
+ | ? | + | +/- | + | + |
Контроль границ массивов | + | ? | - | +/- [149] |
+ | + | + | N/A | + | + | ? | + | N/A [150] |
+ [141] |
+ | + | + | N/A [150] |
+/- [151] |
+ | ? | + | ? | ? | + | + | + [152] |
- |
Цикл foreach | - | +/- [153] |
- | + [154] |
+ | + | - | +/- [155] |
+ | + | + | + | + [156] |
+ | + [157] |
- | + | + | + | + | + | + | + | + | + | + | + | + |
Списковые включения | - | - | - | - | -/+ [158] |
- | - | + | + | ? | - | - | - | + | +[159] | - | + | ? | - | + | ? | - | + | + | + | - | +/- | - |
Целые числа произвольной длины | - | - | - | - | + [160] |
+ | ? | + | + | +[161] | + | + [162] |
+ | + | + | - | + [160] |
+ | +/- [163] |
+ | + | +/- [164] |
+ [165] |
+ | + [160] |
- | + [166] |
- |
Целые числа с контролем границ | - | + | - | - | - | - | ? | - | - | +/-[139] | - | - | - | - | +[167] | + | - | - [168] |
- | - | ? | - | - | ? | - | + | - | - |
Объектно-ориентированные возможности[править]
Возможность | Язык | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | VB.NET | Delphi | OCaml | PureBasic | |
Интерфейсы | + | ? | +/- [169] | + [170] | + | + | ? | N/A | + | + | + | + | ? | N/A | N/A[171] | - | + | +/-[172] | + | + | ? | + [173] |
? | ? | + | + | + | + |
Мультиметоды | - | - | - | -/+[174] | -/+[175] | - | - | N/A | - | - | + | - [176] |
- | N/A |
+ | - | - | - [176][177] |
- | - [176] |
- [176] |
-/+ [178] |
- | - | - | - | - | - |
Mixins | - | ? | - | -/+[179] | - | + | ? | N/A | ? | ? | + [180] |
+ |
? | N/A |
+ | - | ? | ? |
+ [181] |
+ [182] |
+ |
? | + | + | ? | +[183] | ? | N/A |
Переименование членов при наследовании | - | ? | N/A | -/+[184] | - | ? | + | N/A | - | ? | - | - | ? | N/A | - | - | - | -/+ | - | - | ? | N/A [185] |
? | - | - | - | ? | - |
Множественное наследование | - | ? | N/A | + | - | - | + | N/A | - | ? | - | - | ? | N/A | + | - | - | + | - | + | - | N/A [185] |
? | - | - | - | + | +/- |
Решение конфликта имён при множественном наследовании | N/A | ? | N/A | + [186] |
N/A | N/A | + [187] |
N/A | N/A | ? | ? | N/A | ? | N/A | +[188] | N/A | N/A | + | N/A | + | N/A | N/A [185] |
? | N/A | N/A | N/A | ? | ? |
Функциональные возможности[править]
Возможность | Язык | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | VB.NET | Delphi | OCaml | PureBasic | |
Декларации чистоты функций | - | - | - | -/+ | - | +[189] | - | - | - | ? | - | - | - | + | - | - | - | - | - | - | - | + [190] |
- | - | - | - | - | - |
First class functions | + | ? | -/+[191] | +[192] | + | + | ? | + | + | ? | + | - | + |
+ | + | + |
+ |
+ | +[193] | + |
+ | + | + | + | ? | +/- [194] |
+ | ? |
Анонимные функции | - | ? | - | +[195] | +[196] | + | ? | + | + | ? | + | + | + |
+ | +[197] | - |
+ |
+ | + |
+/-[198] |
+ | + | + | + | + | +/- [194] |
+ | + |
Лексические замыкания | - | - | - | + [199] | + | + | + | + | + | ? | + | +[200] | + | + | + | - | + | + | +[201] | + | + | + | + | + | + | +/- [202] |
+ | - |
Частичное применение | - | ? | - | +/- [203] |
? | + [204] | ? | ? | + | ? | ? | - | +[205] | + | - | - | + | - [206] |
- | + [207] |
+ | -/+ [208] |
+ | ? | ? | ? | + | ? |
Каррирование | - | - | - | +/- [209] | + | + [204] | - | - | + | ? | - | - | + |
+ | - | - |
- |
+ | + |
+ |
+[210] | -/+ [208] |
+ | - | - | +/- [211] | + | - |
Разное[править]
Возможность | Язык | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | VB.NET | Delphi | Ocaml | PureBasic | |
Макросы | - | -/+ | + [212] |
+ [212] |
+/- | - | - | +/- | - | ? | - | - | - | +/- [213] |
+ | - | + |
+[214] | - | + |
+/- | + | - | - | + [215] |
- | -/+ [216] |
+ |
Шаблоны/Generics | - | + | - | + | + | + | + | N/A [217] |
+ | - | + | + | N/A [217] |
- [218] |
N/A [217] |
+ | + | N/A [217] |
N/A [217] | N/A [217] |
N/A [217] |
+ | + | N/A [217] |
+ | + [219] |
+/- | ? |
Поддержка Unicode в идентификаторах | - | + | + [220] |
+ [221] |
+ | + | ? | - | + | + | + | + | + | + | +[222] | - | + | +/- | -/+ | + [223] |
+ [224] |
-/+ [225] |
+ | + | + | + | + | + |
Перегрузка функций | - | + | - | + | + | + | - | + | + | - | + | + | -/+ [226] |
+ | +[227] | - | + | - [228] |
- | - [229] |
- | - | + | ? | + | + | + | - |
Динамические переменные | - | ? | - | - | + | - | ? |
- | ? | - | ? | ? | ? | +/-[230] |
+[231] |
- | ? | + |
- | - | ? | +/- | ? | ? | + | ? | ? | - |
Именованные параметры | - | + | - | - | + [232] |
- | - | - | +/- | - | + | - | -/+ [233] |
- | +[234] | + | + | + | - | + | + | - | + | -/+ [235] |
+ | -/+ [236] |
+ | - |
Значения параметров по умолчанию | + | + | - | + | + [232] |
+ | - | +/- [237] |
- | + | + | - | + | - | +[238] | + | + | +/- [239] |
+ | + | + | - | + | +/- | + | + | + | + |
Локальные функции | + | + | -/+ [240] |
+ [241] |
+ | + | - | + | + | + | - | +/- [242] |
+ | + | +[243] | + | + | +/- | + | + | + | + | + | - | +/- | + | + | ? |
Сопоставление с образцом | - | - | - | - | + | - | - | + | + | - | - | - | - | + | +/-[244] | - | + | + | - | - [229] |
- | + | + | ? | - | - | + | ? |
Контрактное программирование | - | + [245] |
- | - | + [246] |
+ | + | ? | +/- [246] |
? | +/- | +/- [247] |
? | + [248] |
+ | - | + | ? | - | +/- | +/- | - | ? | ? | + [246] |
- | - | ? |
Наличие библиотек для работы с графикой и мультимедиа (OpenGL/WebGL/OpenML, OpenAL, DirectX) | + | ? | + | + | +[249] | + [250] | ? | ? | +[249] | ? | ? | + | + | + | +[251] | + | ? | ? | -/+[252] | + | ? | + | + | ? | + | + | ? | +[253] |
Стандартизация[править]
Язык | Active Oberon | Ada | C | C++ | C# | D | Eiffel | Erlang | F# | Go | Groovy | Java | JavaScript | Haskell | Common Lisp | Modula-3 | Nemerle | Perl | PHP | Python | Ruby | Rust | Scala | Smalltalk | VB.NET | Delphi | OCaml | PureBasic |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Стандарты | - | ISO ANSI ГОСТ | ISO ANSI | ISO | ISO ECMA | - | ISO ECMA | - | - | ? | - | - | ECMA | Haskell 2010 | ANSI | - | - | - | PSR | PEP 8 | ISO | - | - | ANSI | - | - | - | - |
Примечания[править]
- ↑ Императивный/Haskell. Монады позволяют выполнять императивные действия.
- ↑ Несмотря на отсутствие встроенных средств поддержки ООП, реализация объектно-ориентированного подхода возможна. В качестве наиболее ярких примеров можно привести библиотеки OpenGL, OpenCL, OpenMAX AL и т. п., которые реализуют именно ООП средствами языка С.
- ↑ ООП/Javascript. Прототипная модель ООП.
- ↑ ООП/Haskell. Классы типов и семейства типов перекрывают возможности ООП.
- ↑ ООП/Rust. Объектно-ориентированное программирование как таковое на уровне языка не поддерживается, но язык позволяет реализовать большинство понятий ООП при помощи других абстракций; см. Rust Frequently Asked Questions // Design Patterns (англ.). — Официальный FAQ о языке Rust. — «Many things you can do in OO languages you can do in Rust, but not everything, and not always using the same abstraction you’re accustomed to. […] There are ways of translating object-oriented concepts like multiple inheritance to Rust, but as Rust is not object-oriented the result of the translation may look substantially different from its appearance in an OO language.» Архивировано из первоисточника 29 января 2018.[недоступная ссылка] Проверено 24 июля 2017.
- ↑ присваивание как типизируемое выражение (не оператор), тернарная операция, функции с неограниченным числом параметров, void* как небезопасная форма параметрического полиморфизма
- ↑ Робинсон определил шаблоны С++ как полный по Тьюрингу функциональный язык программирования. Саймон Пейтон-Джонс и Тим Шерд назвали работу Робинсона провокационной, природу шаблонного метапрограммирования — нелепой и причудливой, и отметили, что функциональные программисты не спешат использовать С++: Sheard T., Jones S.P. Template Metaprogramming in Haskell // Haskell Workshop. — Pittsburgh: ACM 1-58113-415-0/01/0009, 2002.
- ↑ Пространства имён функций и данных разделены, для работы с функциями высших порядков используется специальный синтаксис
- ↑ Гомоиконность отсутствует, но RTTI есть
- ↑ Рефлексивный/Rust. В процедурных макроопределениях (procedural macros), см. Procedural Macros (and custom Derive) (англ.). — The Rust Programming Language, 1st Edition. Проверено 24 июля 2017.
- ↑ void*
- ↑ шаблоны являются отдельным мини-языком
- ↑ Логический/Haskell. Изначально инструментов для логического программирования не встроено, но есть сторонние библиотеки. Существует академический функционально-логический язык Curry, берущий Haskell за основу.
- ↑ Логический/Common Lisp. Логическая парадигма изначально в язык не встроена, но реализуется средствами языка.
- ↑ LINQ
- ↑ В языке существует множество декларативных конструкций, и, более того, возможность создавать свои, с помощью макросов.
- ↑ Декларативный/Perl. Только регулярные выражения.
- ↑ Распределённый/Ada. См. Annex E. Distributed Systems.
- ↑ 19,0 19,1 Распределённый/C и C++. Многие распространённые компиляторы поддерживают директивы для распараллеливания в рамках технологий MPI и OpenMP.
- ↑ Распределённый/C#. Существуют проекты распределённых модификаций языка, например Parallel C#.
- ↑ std.parallelism
- ↑ Распределённый/Haskell. Модель языка подразумевает распределённое использование, при этом не требуя от программиста усилий на реализацию распределённости. Один из поддерживающих эту возможность компиляторов — Glasgow Distributed Haskell.
- ↑ 23,0 23,1 ANSI стандарт языка предусматривает опциональные декларации типов, которые какие-либо конкретные реализации могут использовать по своему усмотрению. Большинство современных реализаций CL принимают декларации типов в расчёт, и используют для статической проверки типов и в целях оптимизации.
- ↑ Статическая типизация/Perl. С версии 5.6. Только для не встроенных типов.
- ↑ Статическая типизация/Smalltalk. Возможность статической типизации есть в диалекте Smalltalk — Strongtalk'е.
- ↑ Динамическая типизация/C#. Посредством специального псевдо-типа
dynamic
с версии 4.0. - ↑ Динамическая типизация/F#. Компилятор поддерживает синтаксический сахар в виде преобразования использования оператора (?)
xml?name
в вызовxml.op_Dynamic("name")
, на базе чего может быть реализована имитация динамической типизации. - ↑ Динамическая типизация/Haskell. Обеспечивается модулем
Data.Dynamic
. - ↑ Динамическая типизация/Rust. С помощью типажа
Any
, см. The Rust Standard Library // std::any (англ.). Проверено 25 июля 2017. - ↑ Динамическая типизация/VB.NET. Контролируемо с помощью Option Strict.
- ↑ Динамическая типизация/Delphi. Посредством специального типа Variant.
- ↑ Явная типизация/Erlang. Можно использовать т. н. type test BIFs. См
- ↑ Явная типизация/Perl. См. Prototypes в man perlsub.
- ↑ Явная типизация/Python. Частично в Python 3.0.
- ↑ Явная типизация/Smalltalk. Есть в Strongtalk.
- ↑ var, dynamic etc.
- ↑ Неявное приведение типов/Ada. См. 4.6 Type Conversions.
- ↑ Расширение для примитивных типов, приведение к супертипу для классов.
- ↑ Неявное приведение типов без потери данных/Rust. В очень небольшом наборе ситуаций, в частности: приведение ссылки к указателю; изменяемой ссылки (указателя) к неизменяемой ссылке (указателю); объекта определённого типа к объекту с типажом, реализованным этим типом. См. Coercions (англ.). — The Rustonomicon. Проверено 24 июля 2017.
- ↑ Неявное приведение с потерей данных/Perl. При сложении строки с числом:
$a = '5aa'; print $a + 0;
Напечатает: 5
- ↑ Неявное приведение в неоднозначных ситуациях/Perl. Не совсем корректно, так как в Perl эти ситуации однозначны:
1 + "2" # 3
и1 . "2" # "12"
- ↑ Макрос DEFTYPE
- ↑ Abstract types
- ↑ 44,0 44,1 Вывод типов/C++. Поддержка вывода типов имплементируется в C++11 с использованием ключевых слов
auto
иdecltype
. - ↑ 45,0 45,1 45,2 45,3 Вывод типов/Common Lisp. Некоторые компиляторы Common Lisp, такие как SBCL, поддерживают частичный вывод типов.
- ↑ auto function = [&](int a){} в c++11
- ↑ Параметрический полиморфизм с ковариантностью/C#. Доступно начиная с C# 4.0 для типов интерфейсов и делегатов.
- ↑ Параметрический полиморфизм высших порядков/Rust. См. RFC 324.
- ↑ Информация о типах в runtime/Ada. Точный тип узнать можно (Ada.Tags), но полной поддержки отражения в языке нет. Можно узнать имя, предков, интерфейсы, сериализовать объект, но нельзя запросить список методов.
- ↑ Информация о типах в runtime/С++. Можно сравнить типы на точное совпадение, узнать имя типа (typeid. Архивировано из первоисточника 4 марта 2009.), приводить типы вниз по иерархии наследования.
- ↑ См. встроенную функцию ref и метод isa
- ↑ см. TypeTags
- ↑ Open-source компилятор (интерпретатор)/Smalltalk. В любом диалекте Smalltalk исходники всего, кроме виртуальной машины, (то есть библиотека классов, компилятор в байткод, среда разработки, сторонние библиотеки и пр.) принципиально открыты — это свойство языка. Из основных диалектов исходники виртуальной машины открыты у GNU Smalltalk, Squeak и Strongtalk.
- ↑ Open-source компилятор (интерпретатор)/Delphi. FreePascal и Lazarus.
- ↑ Возможность компиляции/Erlang. HiPE — High Performance Erlang. Доступен только для *nix-систем.
- ↑ Существуют PHP-компиляторы, вполне корректно компилирующие любые PHP-скрипты. Например, Roadsend PHP Compiler.
- ↑ Возможность компиляции/Smalltalk. Стандартная реализация в Smalltalk — это прозрачная компиляция в байт-код (в момент сохранения изменённого исходного кода) с последующим исполнением на виртуальной машине, часто с использованием JIT-компилятора. Однако некоторые диалекты поддерживают прямую компиляцию в машинные коды. В частности, к таким диалектам относятся Smalltalk MT и Smalltalk/X.
- ↑ Bootstrapping-компилятор/Java. Java Compiler API появилось в версии 6.0.
- ↑ Narcissus[en]
- ↑ Например, SBCL
- ↑ Bootstrapping-компилятор/Python. Проект PyPy. Архивировано из первоисточника 16 ноября 2007.
- ↑ Bootstrapping-компилятор/Smalltalk. Компилятор в байт-коды изначально написан на самом Smalltalk и исполняется внутри виртуальной машины. Кроме этого также есть примеры виртуальных машин Smalltalk, написанных на самом Smalltalk — к ним, в частности, относится виртуальная машина Squeak, написанная на подмножестве Smalltalk, которое потом транслируется в C и компилируется в машинные коды. При этом собственно разработка и отладка виртуальной машины Squeak осуществляется внутри работающей системы Squeak.
- ↑ Многопоточная компиляция/Go. [1].
- ↑ Интерпретатор командной строки/Ada. Business Shell (BUSH). Архивировано из первоисточника 18 января 2008.
- ↑ 65,0 65,1 Интерпретатор командной строки/C++. C++ интерпретатор CINT. Архивировано из первоисточника 20 ноября 2017.
- ↑ компиляция на лету с помощью rdmd
- ↑ Rhino Shell.
- ↑ В диалекте GNU Smalltalk реализована поддержка командной строки.
- ↑ Интерпретатор командной строки/Delphi. PascalScript.
- ↑ Условная компиляция/Ada. Поскольку использование препроцессора существенно осложняет работу утилит, отличных от компилятора, работающих с исходными текстами, в стандарт эта возможность не входит. Здесь: Conditional Compilation. Архивировано из первоисточника 30 ноября 2007. описывается, как можно организовать условно компилируемый код. В качестве резервного варианта предоставляется препроцессор gnatprep.
- ↑ Условная компиляция/Java. Утверждения (операторы assert) всегда включаются компилятором в байт-код и могут быть разрешены (по умолчанию запрещены, то есть игнорируются) при запуске виртуальной машины ключом -ea/-enableassertion.
- ↑ [2] Архивная копия от 31 января 2008 на Wayback Machine
- ↑ Макросы лиспа позволяют при компиляции вычислять произвольные выражения, включая, естественно, конструкции ветвлений. Кроме того, имеется также примерный аналог #ifdef из Си.[3][4]
- ↑ Компилятор должен решать, какие классы будут представлены «простыми» типами и будут, в том числе, размещаться в стеке.
- ↑ Создание объектов на стеке/Haskell. В GHC при помощи Unboxed Types / Unboxed Arrays.
- ↑ Стандарт языка предусматривает декларацию DYNAMIC-EXTENT, которая может трактоваться компилятором как указание выделить место под объект на стеке.
- ↑ Создание объектов на стеке/Delphi. В Delphi имеется 2 объектных модели — старая (унаследована из Turbo Pascal) и новая. Создание объектов на стеке возможно только в старой объектной модели.
- ↑ 79,0 79,1 79,2 79,3 79,4 79,5 79,6 Через FFI (foreign function interface)
- ↑ Можно с помощью модуля стандартной библиотеки — ctypes.
- ↑ 81,0 81,1 Позволяется в
unsafe
-блоках (участках кода, помеченных как небезопасные). - ↑ Неуправляемые указатели/Smalltalk. В Smalltalk есть возможность низкоуровневой работы с памятью, но только в адресном пространстве, предоставляемом виртуальной машиной.
- ↑ unsafe + System.Runtime.InteropServices
- ↑ Ручное управление памятью/Smalltalk. При низкоуровневой работе в пространстве памяти, предоставляемом виртуальной машиной, можно вручную создавать и удалять объекты, записывая данные в соответствующие адреса памяти. Аналогично можно вручную управлять размещением объектов в памяти.
- ↑ Сборка мусора/Ada. Только на некоторых платформах (.NET и JVM) или при помощи библиотек (AdaCL:GC). Тем не менее, практически все программы на Ada могут работать как с ним, так и без него. В этом смысле к сборке мусора применительно к Аде следует относиться не как к инженерному решению, а как к оптимизации управления памятью.
- ↑ Сборка мусора/C. В стандарте языка и в стандартных библиотеках нет сборки мусора. Однако существуют сборщики мусора для C и C++ в виде библиотек. Например, BoehmGC[en]
- ↑ В новом стандарте C++0x предполагается сборка мусора для интеллектуальных указателей
- ↑ Сборка мусора/Rust. Через
Rc
илиArc
— умные указатели со счётчиком ссылок, часть стандартной библиотеки. Синтаксис языка позволяет вывести время жизни объекта статически, во время компиляции, что делает динамическую сборку мусора в большинстве случаев ненужной. - ↑ Сборка мусора/Delphi. Если не считать Delphi.NET.
- ↑ Инструкция goto/Java. Является зарезервированным словом.
- ↑ Специальный оператор GO. Все конструкции циклов в CL, фактически, являются макросами-надстройками над этой инструкцией.
- ↑ Целевая метка должна находиться в том же файле, в том же контексте. Имеется в виду, что вы не можете ни перейти за границы функции или метода, ни перейти внутрь одной из них [5].
- ↑ Инструкция goto/Ruby. В языке goto нет, но есть библиотека. Архивировано из первоисточника 14 декабря 2007. реализующая его.
- ↑ Инструкция goto/Smalltalk. В стандарте языка goto нет, но существуют библиотеки, реализующие функциональность goto через управление стеком исполнения. Используются крайне редко, это скорее proof of concept(англ.)
- ↑ Макрос RETURN. Фактически, является частным случаем RETURN-FROM.
- ↑ заменяется исключениями, также реализуется с помощью Camlp4 http://code.google.com/p/ocaml-break-continue/
- ↑ Специальный оператор RETURN-FROM
- ↑ Принимает необязательный числовой аргумент, который сообщает ему выполнение какого количества вложенных структур необходимо прервать [6].
- ↑ Есть возможность указать число вложенных циклов, которые нужно прервать
- ↑ Можно либо повторить выполнение метода, либо пробросить исключение далее
- ↑ Java-style try-catch блок реализуется макросом handler-case. Кроме того, в возможности системы обработки исключений Common Lisp входит система т. н. перезапусков(restarts), которые позволяют обрабатывать исключения «изнутри» без раскрутки стека вызовов функций
- ↑ При помощи оператора eval
- ↑ 103,0 103,1 103,2 103,3 Вместо механизма исключений, в Rust применяется сопоставление опционального значения с образцом, то есть обязательная проверка наличия значения или ошибки.
- ↑ 104,0 104,1 104,2 При использовании библиотеки PBOSL
- ↑ Блок finally/Ada. В стандарте языка finally нет, но существуют библиотеки, реализующие функциональность finally. Используются крайне редко, это скорее proof of concept(англ.)
- ↑ MDN — MDC
- ↑ Специальный оператор UNWIND-PROTECT
- ↑ 108,0 108,1 Начиная с версии 5.5
- ↑ реализуется на camlp4 http://bluestorm.info/camlp4/dev/try/pa_tryfinally.ml.html[недоступная ссылка]
- ↑ При помощи нескольких последовательных catch
- ↑ Java-style try-catch блок реализуется макросом handler-case. Кроме того, в возможности системы обработки исключений Common Lisp входит система т. н. перезапусков(restarts), которые позволяют обрабатывать исключения «сверху» без раскрутки стека вызовов функций
- ↑ При помощи eval or {…}
- ↑ Реализован перезапуск тела активного объекта (активности), для этого тело объекта помечается модификатором {SAFE}
- ↑ Частично реализуются нестандартным модулем Runops::Resume. Архивировано из первоисточника 18 сентября 2011.
- ↑ Ключевое слово retry
- ↑ Конструкции yield return, запросы LINQ, в FCL 4.0 войдёт тип Lazy.
- ↑ Seq-генераторы, модуль Lazy стандартной библиотеки F#.
- ↑ Однако, данную возможность можно реализовать на макросах
- ↑ Данная возможность реализована на макросах
- ↑ Spl-интерфейсы итераторов и конструкция yield, начиная с версии 5.5.
- ↑ Ленивые вычисления/Ruby. В языке ленивых вычислений нет, но есть библиотека. Архивировано из первоисточника 12 сентября 2011. реализующая их.
- ↑ Конструкции Linq.
- ↑ модуль Lazy стандартной библиотеки Ocaml.
- ↑ setcontext et al. (UNIX System V and GNU libc)
- ↑ Конструкции yield return и await
- ↑ Реазилуется сторонними библиотеками, например cl-cont
- ↑ Только для байт-кода http://okmij.org/ftp/Computation/Continuations.html#caml-shift
- ↑ Fibers
- ↑ Легковесные процессы/Java. Вплоть до Java 1.1.
- ↑ Только в некоторых реализациях.
- ↑ Это не стандартные лёгкие процессы
- ↑ Легковесные процессы/Python. Используя Stackless Python.
- ↑ Класс Fiber в Руби 1.9+
- ↑ Легковесные процессы/Rust. В библиотеке futures.
- ↑ Монадические потоки выполнения, реализованы в библиотеке Lwt
- ↑ PHP позволяет возвращать из функции/метода массив и разворачивать его конструкцией list что работает также как кортежи, с версии 5.4 появилась возможность разворачивать возвращаемые массивы сразу(array dereferencing)
- ↑ 137,0 137,1 Алгебраические типы данных/Ada и Delphi. Через механизм вариантных записей.
- ↑ 138,0 138,1 138,2 138,3 138,4 138,5 138,6 138,7 В динамических языках механизм алгебраических типов данных не имеет смысла.
- ↑ 139,0 139,1 Может быть реализовано средствами языка
- ↑ Через механизм case-классов
- ↑ 141,0 141,1 Массивы/Haskell. С помощью Data.Array.
- ↑ Динамические массивы/C. «Из коробки» данной возможности нет, однако похожий функциональность можно реализовать, используя функцию realloc.
- ↑ Динамические массивы/Java. С помощью java.util.Vector (в стандартной библиотеке).
- ↑ Динамические массивы/Rust.
Vec
в стандартной библиотеке. - ↑ map и unordered_map в стандартной библиотеке
- ↑ Ассоциативные массивы/Java. С помощью java.util.HashMap (в стандартной библиотеке).
- ↑ Ассоциативные массивы/Haskell. С помощью Data.Map
- ↑ Ассоциативные массивы/Rust.
HashMap
в стандартной библиотеке. - ↑ Контроль границы массивов/С++. Для массивов контроля нет, однако в контейнерах STL, таких как std::vector, std::array есть метод at с контролем границ.
- ↑ 150,0 150,1 Контроль границ массивов/Perl, PHP и JavaScript. В языке нет массивов со статическими границами, присваивание элементу за текущими границами массива просто расширяет границы массива.
- ↑ Существует только в виде SPL структуры данных. Стандартные массивы не предоставляют контроля границ — присваивание элементу за текущими границами массива — просто расширяет границы массива.
- ↑ Контроль границ массивов/Ocaml. Можно отключить на этапе компиляции с помощью ключа -unsafe
- ↑ Цикл foreach/Ada. Методы Iterate и Reverse_Iterate различных контейнеров, входящих в библиотеку Ada.Containers.
- ↑ Цикл foreach/C++. В C++11
for(auto x : some_array){}
— не может изменять элементы,for(auto& x : some_array){}
— может изменять элементы. - ↑ Цикл foreach/Erlang. В виде функции
foreach/3
из модуляlists
. - ↑ Цикл foreach/JavaScript. С версии 1.6 [7].
- ↑ Цикл foreach/Lisp. Макрос LOOP в составе стандартной библиотеки. Представляет собой «язык в языке» с большим количеством возможностей.
- ↑ List comprehensions/C#. «Query Comprehension» можно считать за List Comprehension только с большой натяжкой.
- ↑ LOOP et al.
- ↑ 160,0 160,1 160,2 Целые числа произвольной длины/.NET. Посредством типа
System.Numerics.BigInteger
, включённого в FCL версии 4.0. - ↑ Включены в стандартную библиотеку
- ↑ Целые числа произвольной длины/Java. С помощью классов
BigInteger
иBigDecimal
. - ↑ Для вычислений с произвольной точностью PHP предоставляет Двоичный калькулятор, который поддерживает числа любого размера и точности, представленные в виде строк [8] .
- ↑ Целые числа произвольной длины/Rust.
BigInt
в библиотеке num. - ↑ Целые числа произвольной длины/Scala. С помощью классов
BigInteger
иBigDecimal
. - ↑ Целые числа произвольной длины/OCaml. В помощью модуля
Num
иBig_int
. - ↑ Пример: Тип (INTEGER 0 9) включает в себя все цифры от 0 до 9
- ↑ Целые числа произвольной длины/Perl. С помощью модуля
Tie::Scalar
. - ↑ Интерфейсы традиционно реализуются структурами с указателями на функции, входящие в интерфейс. Пример реализации и использования — библиотеки OpenGL, OpenMAX AL и т. п..
- ↑ Множественное наследование абстрактных классов
- ↑ Похожая функциональность реализуется макросами и средствами CLOS.
- ↑ Через множественное наследование от классов с методами-заготовками. См
- ↑ Типажи (traits).
- ↑ Могут быть реализованы с помощью паттерна Visitor(Посетитель)
- ↑ Эмуляция через dynamic
- ↑ 176,0 176,1 176,2 176,3 Реализуется сторонними библиотеками
- ↑ появятся(?) в Perl 6
- ↑ Могут быть реализованы с помощью паттерна Visitor (Посетитель).
- ↑ Могут быть реализованы с помощью наследования шаблонов Примесь (программирование)#.D0.AD.D0.BC.D1.83.D0.BB.D1.8F.D1.86.D0.B8.D1.8F
- ↑ Groovy — Category and Mixin transformations. Архивировано из первоисточника 7 июля 2012.[недоступная ссылка] Проверено 24 июля 2012.
- ↑ Начиная с PHP версии 5.4 присутствует в виде trait
- ↑ Через множественное наследование и/или изменение атрибутов произвольного объекта во время выполнения
- ↑ Подмешивание реализации интерфейсов через ключевое слово implements. См. страницы 10-7 и 10-8 в Object Pascal Guide.
- ↑ Переименование членов при наследовании не поддерживается c++, однако можно сэмулировать через закрытое наследование, открывая члены, которые не нужно переименовать через директиву using, а если нужно переименовать — просто определить метод с новым названием и вызвать в нём метод родителя
- ↑ 185,0 185,1 185,2 В Rust нет наследования, только реализация типажей (traits, аналог интерфейсов).
- ↑ Директива using
- ↑ Для каждого члена класса — выбор дублирование (через переименование), или слияние (иначе, если не было переопределения)
- ↑ CLHS: Section 4.3.5
- ↑ Functions — D Programming Language 2.0 — Digital Mars. Архивировано из первоисточника 2 февраля 2019.[недоступная ссылка] Проверено 5 сентября 2009.
- ↑
const fn
в Rust 2018; см. The Rust Reference — Const functions - ↑ в форме указателей на функции
- ↑ std::function в c++0x
- ↑ Functional Programming in PHP
- ↑ 194,0 194,1 Появились в Delphi2009, как анонимные функции. Ранее — через указатели.
- ↑ C++0x. Лямбда-выражения в C++0x
- ↑ Анонимные делегаты присутствуют в языке с версии 2.0. В C# 3.0 появились полноценные анонимные функции.
- ↑ Макрос LAMBDA
- ↑ С существенными ограничениями
- ↑ lambda-функции в c++0x поддерживают замыкания как по ссылке, так и по значению
- ↑ Через анонимные классы
- ↑ Начиная с версии 5.3
- ↑ Появились в Delphi2009, как анонимные функции.
- ↑ boost::bind, std::bind1st, std::bind2nd или сэмулировать с помощью анонимных функций
- ↑ 204,0 204,1 с помощью возвращения делегата
- ↑ С помощью Function.prototype.bind
- ↑ Реализуется сторонними библиотеками, например Sub::Curry и Sub::Curried
- ↑ functools.partial в стандартной библиотеке начиная с Python 2.5
- ↑ 208,0 208,1 По состоянию в Rust 1.19, может быть реализовано при включении
#![feature(conservative_impl_trait)]
. - ↑ с помощью lambda-функций в c++0x
- ↑ Proc#curry, появился в Ruby 1.9
- ↑ Начиная с Delphi 2009
- ↑ 212,0 212,1 Макросы/C. Посредством препроцессора C.
- ↑ Макросы/Haskell. Template Haskell — препроцессор, встроенный в GHC.
- ↑ Фильтры [9], в том числе, C/C++ препроцессор Filter::cpp
- ↑ Встроены в Visual Studio (нет в Express Edition)
- ↑ Штатный препроцессор camlp4
- ↑ 217,0 217,1 217,2 217,3 217,4 217,5 217,6 217,7 Неприменимо в языках с динамической типизацией.
- ↑ Generics/Haskell. Прямых аналогов шаблонов в языке нет, однако имеются не менее мощные средства обобщённого программирования.
- ↑ Generics/Delphi. Доступно начиная с Delphi 2009.
- ↑ Unicode в идентификаторах/C. Доступно в компиляторах gcc начиная с 4.2
- ↑ Unicode в идентификаторах/C++. Доступно в компиляторах от MS, начиная с MSVS++ 2005 и в gcc начиная с 4.2
- ↑ В большинстве современных реализаций
- ↑ Unicode в идентификаторах/Python. Доступно начиная с Python 3.0.
- ↑ Unicode в идентификаторах/Ruby. Доступно начиная с Ruby 1.9.
- ↑ По состоянию в Rust 1.19, поддерживается с некоторыми ограничениями при включении
#![feature(non_ascii_idents)]
. - ↑ Перегрузка функций/JavaScript. Можно сымитировать, используя проверку передаваемых параметров с помощью рефлексии.
- ↑ Обобщённые функции можно перегружать по типам или значениям нескольких параметров
- ↑ Только перегрузка операторов [10].
- ↑ 229,0 229,1 Перегрузка функций и сопоставление с образцом/Python. Реализовано в сторонней библиотеке PEAK-rules.
- ↑ implicit-parameters. Архивировано из первоисточника 7 мая 2010.[недоступная ссылка] Проверено 11 марта 2010.
- ↑ макросы DEFVAR и DEFPARAMETER, а также декларация SPECIAL, создают динамические биндинги.
- ↑ 232,0 232,1 Именованные аргументы и параметры по умолчанию/C#. Доступно начиная с C# 4.0.
- ↑ Именованные параметры/JavaScript. Можно сымитировать, передав в качестве параметра функции объект:
f ({param1: "value1", param2: "value2"})
. - ↑ Спецификатор «&key» в списке аргументов объявляемой функции объявляет именованный параметр.
- ↑ Именованные параметры/Smalltalk. Можно называть методы в стиле
сделатьЧтоНибудьС:используя:и:
— в таком случае двоеточия обозначают места, куда будут подставляться параметры при вызове метода, напримерсделатьЧтоНибудьС: парам1 используя: парам2 и: парам3
. Названия подбирают таким образом, чтобы при вызове было понятно, для чего будут использоваться параметры. - ↑ Именованные параметры/Delphi: Могут использоваться при вызове OLE:
Word.Openfile(filename='1.doc')
- ↑ Значения параметров по умолчанию/Erlang. Можно сымитировать с помощью арности функции.
- ↑ «&key» и «&optional» параметры допускают значения по умолчанию
- ↑ Значения параметров по умолчанию/Perl. Можно элементарно сымитировать, см. [11] Архивная копия от 22 июня 2008 на Wayback Machine
- ↑ Локальные функции/С. Поддерживаются в компиляторе gcc как нестандартное расширение языка, см. [12].
- ↑ Локальные функции/С++. с помощью lambda-функций в c++0x
- ↑ Локальные функции/Java. Внутри метода можно определять безымянные (анонимные) локальные классы, которые фактически позволяют создавать экземпляры объектов, перекрывающие методы своего класса.
- ↑ Специальный оператор LABELS
- ↑ Макрос DESTRUCTURING-BIND и EQL спецификатор в обобщённых функциях можно рассматривать как аналоги некоторых подмножеств функциональности сопоставления с образцом.
- ↑ Начиная с Ada 2012.
- ↑ 246,0 246,1 246,2 Посредством библиотеки Code Contracts из состава FCL 4.0.
- ↑ Контрактное программирование/Java. На основе аннотаций Java 5, используя библиотеку OVal и аспектный компилятор AspectJ, а также iContract [13] Архивная копия от 8 января 2011 на Wayback Machine .
- ↑ Контрактное программирование/Haskell. Посредством библиотеки QuickCheck.
- ↑ 249,0 249,1 DirectX через Net, OpenGL через стороннюю библиотеку OpenTK
- ↑ большинство мультимедийных библиотек доступны через обёртку Derelict
- ↑ libraries: cl-opengl
- ↑ Существует реализация OpenGL библиотеки для php — phpOpenGL project (Зеркало на Github)
- ↑ Объявления структур данных, констант и интерфейсов DirectX, OpenGL присутствуют в стандартной библиотеке языка, есть сторонние врапперы для большинства используемых библиотек, в том числе — игровых, звуковых и физических движков.
Терминология[править]
Парадигмы[править]
Императивная[править]
Противоположность декларативному. Императивный язык должен описывать не столько саму задачу (описание, «ЧТО» нужно получить), сколько её решение («КАК» получить). Некоторыми авторами считается, что данное определение скорее относится к «процедурной» парадигме, которая, помимо императивного, включает в себя функциональное программирование.
Объектно-ориентированная[править]
Основана на представлении всего в виде объектов, являющихся экземплярами того или иного класса и воплощает применение концепции абстрагирования. Объект при этом соединяет внутри себя как данные, так и методы, их обрабатывающие. Как правило, поддерживаются характерные возможности: наследование, инкапсуляция и полиморфизм. Некоторые авторы языки без наследования относят к просто «объектным».
Рефлексивная[править]
Наличие в языке мощных механизмов интроспекции, функции eval. Возможность программы на данном языке оперировать собственным кодом как данными.
Функциональная[править]
Позволяет записывать программу как композицию функций. В чистом функциональном языке нет переменных. Так как функции не имеют побочных эффектов, они могут выполняться в любом порядке.
Обобщённое программирование[править]
Обобщённое программирование позволяет записывать алгоритмы, принимающие данные любого типа.
Логическая[править]
Программа представляет собой описание фактов и правил вывода в некотором логическом исчислении. Желаемый результат, который часто записывается как вопрос, получается системой в результате попытки применения описанных правил — путём логического вывода. Интересными особенностями являются отсутствие детерминированности в общем случае, внутренняя склонность к распараллеливанию.
Доказательная[править]
Направлен на разработку алгоритмов и программ с доказательствами их правильности с использованием спецификаций программ.
Декларативная[править]
Противоположность императивному. Декларативный язык описывает не столько решение задачи, сколько саму задачу («ЧТО» нужно получить), а каким образом получить решение, уже должен определять компьютер.
Распределённая[править]
Язык, содержащий специальные конструкции для поддержки распараллеливания программы на несколько компьютеров.
Типизация[править]
Статическая типизация[править]
(См. статическая типизация). Переменные и параметры методов/функций связываются с типом в момент объявления и не могут быть изменены позже.
Динамическая типизация[править]
(См. динамическая типизация). Переменные и параметры методов/функций связываются с типами в момент присваивания значения (или передачи параметра в метод/функцию), а не в момент объявления переменной или параметра. Одна и та же переменная в разные моменты может хранить значения разных типов.
Явная типизация[править]
Типы переменных и параметров указываются явно.
Неявная типизация[править]
Типы переменных и параметров не указываются явно. Неявная типизация может быть и статической, в таком случае типы переменных и параметров вычисляются компилятором.
Явное приведение типов[править]
Для использования переменной какого-либо типа там, где предполагается использование переменной другого типа, нужно (возможно) явно выполнить преобразование типа.
Неявное приведение типов без потери данных[править]
Неявное приведение типов в таких ситуациях, где не происходит потери данных — например, использование целого числа там, где предполагалось использование числа с плавающей точкой.
Неявное приведение типов с потерей данных[править]
Неявное приведение типов в таких ситуациях, где может произойти потеря данных — например, использование числа с плавающей точкой там, где предполагалось использование целого числа.
Неявное приведение типов в неоднозначных ситуациях[править]
Например, использование строки там, где предполагалось число или наоборот. Классический пример: сложить число 1 со строкой «2» — результат может быть как число 3, так и строка «12». Другой пример — использование целого числа там, где ожидается логическое значение (boolean).
Алиасы типов[править]
Возможность определить видимый глобально (за пределами единицы компиляции) алиас типа, полностью эквивалентный исходному типу. Например, typedef в Си. Директива using в C# не подходит под этот критерий из-за локальной области действия.
Вывод типов переменных из инициализатора[править]
Возможность не указывать явно тип переменной, если для неё задан инициализатор. Если возможность действует для локальных переменных, но не действует для полей класса, всё равно ставьте +. Характеристика не применима к языкам с динамической типизацией.
Вывод типов переменных из использования[править]
Возможность не указывать явно тип переменной, если её тип может быть выведен из дальнейшего использования. Если возможность действует для локальных переменных, но не действует для полей класса, всё равно ставьте +. Характеристика не применима к языкам с динамической типизацией.
Вывод типов-аргументов при вызове метода[править]
Возможность не указывать явно типы-аргументы при вызове generic-метода, если они могут быть выведены из типов обычных аргументов.
Вывод сигнатуры для локальных функций[править]
Может ли сигнатура локальной функции быть выведена из использования. Неприменимо для языков с динамической типизацией. Ставьте -, если язык не поддерживает локальные функции.
Параметрический полиморфизм[править]
Наличие типобезопасного параметрического полиморфизма (aka generic types). Подразумевает возможность указывать constraints или type classes[en] для типов-параметров.
Параметрический полиморфизм с ковариантностью[править]
Наличие ко- и контравариантных type parameters. В некоторых языках может быть лишь частичная поддержка (например, только в интерфейсах и делегатах). В таком случае, отмечайте +/-.
Параметрический полиморфизм высших порядков[править]
Возможность создавать type constructors высших порядков (как в Scala). См. Towards Equal Rights for Higher-kinded Types. Архивировано из первоисточника 29 декабря 2009.[недоступная ссылка]
Информация о типах в runtime[править]
Возможность узнать точный тип объекта в runtime.
Информация о типах-параметрах в runtime[править]
Возможность узнать в runtime информацию о типе, с которым инстанциирован generic-тип. Если язык не поддерживает generic-типы, то ставьте -. Если информация о типах стирается в runtime (используется erasure), то ставьте -.
Компилятор/интерпретатор[править]
Open-source компилятор (интерпретатор)[править]
Наличие полноценного open-source компилятора (для интерпретируемых языков — интерпретатора). Если существует open-source компилятор, но он поддерживает не все возможности языка, то ставьте +/- или -/+.
Возможность компиляции[править]
Возможность компиляции в нативный код или в byte-код с возможностью JIT-компиляции. Если язык компилируется в код на другом языке (например, C), который потом компилируется в нативный код, то тоже ставьте +.
Bootstrapping[править]
Наличие полноценного bootstrapping-компилятора (то есть компилятора, написанного на том же языке, который он компилирует, и успешно компилирующего самого себя). Если существует bootstrapping-компилятор, но он поддерживает не все возможности языка, то ставьте +/- или -/+.
Многопоточная компиляция[править]
Возможность компилятора на многопроцессорных системах использовать несколько потоков для ускорения компиляции. Если язык не поддерживает компиляцию, то ставьте x (неприменимо).
Интерпретатор командной строки[править]
Возможность вводить инструкции языка строка за строкой с их немедленным выполнением. Может использоваться в качестве калькулятора.
Условная компиляция[править]
Возможность включать/выключать части кода в зависимости от значения символов условной компиляции (например, с помощью #if … #endif в C++)
Управление памятью[править]
Объекты на стеке[править]
Возможность создавать экземпляры объектов не в куче, а на стеке.
Неуправляемые указатели[править]
Наличие неуправляемых указателей, адресная арифметика, прямой доступ к памяти.
Ручное управление памятью[править]
Возможность явного выделения и освобождения памяти в куче (например, с помощью операторов new и delete в C++).
Сборка мусора[править]
Возможность использовать автоматический процесс сборки мусора (освобождения памяти в куче, занятой неиспользуемыми объектами).
Управление потоком вычислений[править]
Инструкция goto[править]
Поддержка инструкции goto (безусловный переход на метку).
Инструкция break без метки[править]
Поддержка инструкции break без метки (безусловный выход из ближайшего цикла), и соответствующей инструкции continue. Наличие в языке инструкции break, относящегося к switch или другой конструкции, не влияет на это поле.
Инструкция break с меткой[править]
Поддержка инструкции break с меткой (безусловный выход из цикла, помеченного меткой), и соответствующей инструкции continue. Наличие в языке инструкции break, относящегося к switch или другой конструкции, не влияет на это поле.
Поддержка try/catch[править]
Поддержка обработки исключений с помощью try/catch или эквивалентной конструкции.
Блок finally[править]
Поддержка блока finally при обработке исключений или эквивалентной конструкции.
Блок else (исключения)[править]
Поддержка блока else при обработке исключений (действия, выполняющиеся при завершении блока try без исключения).
Перезапуски[править]
Исключения, не раскручивающие стек вызовов. Возможность из места перехвата исключения вернуться в место установки перезапуска.
Легковесные процессы[править]
Эмуляция многопоточности рантаймом самого языка. В пределах одного потока ОС (или нескольких) выполняется множество потоков исходного кода
Типы и структуры данных[править]
Многомерные массивы[править]
Наличие встроенных в язык многомерных массивов. Если язык поддерживает только массивы массивов, ставьте +/-
Динамические массивы[править]
Наличие встроенных в язык динамических массивов (способных изменять свой размер во время выполнения программы). Если динамические массивы представлены только векторами (то есть только одномерными массивами) или векторами векторов, ставьте +/-
Ассоциативные массивы[править]
Наличие встроенных в язык ассоциативных массивов или хеш-таблиц.
Цикл foreach[править]
Наличие возможности перебрать все элементы коллекции с помощью цикла foreach. Если в языке есть эквивалентная или более сильная возможность (наподобие list comprehensions), то будет +.
Списковые включения[править]
Наличие списковых включений (или их аналога).
Кортежи[править]
Возможность вернуть из функции/метода кортеж (tuple) — неименованный тип данных, содержащий несколько безымянных полей произвольного типа.
Целые числа произвольной длины[править]
Поддержка целых чисел неограниченной разрядности. Должна быть возможность записать сколь угодно большое целое число с помощью литерала.
Целые числа с контролем границ[править]
Возможность определить тип, значениями которого могут быть целые числа только определённого интервала, например [-5..27], при этом присвоение переменной такого типа значения, выходящего за указанные рамки, должно вызывать ошибку.
Объектно-ориентированные возможности[править]
Интерфейсы[править]
Семантическая и синтаксическая конструкция в коде программы, используемая для специфицирования услуг, предоставляемых классом.
Множественное наследование[править]
Возможность наследовать класс сразу от нескольких классов (не интерфейсов).
Мультиметоды[править]
Динамическая (run time) диспетчеризация функции в зависимости от типов нескольких аргументов.
В языках с «message passing» ООП похожая функциональность реализуется паттерном «Visitor».
Переименование членов при наследовании[править]
Возможность в наследнике изменить имя поля/метода предка.
Решение конфликта имён при множественном наследовании[править]
При множественном наследовании — решение для случая ромбовидного наследования (B потомок A, C потомок A, D потомок B и C). Решение может приниматься как для всего класса, так и для каждого поля/метода в отдельности.
Функциональные возможности[править]
First class functions[править]
Функции в данном языке являются объектами первого класса.
Лексические замыкания[править]
Возможность использовать локальную или лямбда-функцию (анонимный делегат) за пределами функции-контейнера с автоматическим сохранением контекста (локальных переменных) функции-контейнера
Частичное применение[править]
Возможность фиксировать часть аргументов функции, то есть имея функцию , создать функцию , где . Не следует путать с каррированием (оператор каррирования — один из вариантов реализации частичного применения).
Разное[править]
Макросы[править]
Наличие в языке макросистемы, обрабатывающей код программы до времени её компиляции и/или выполнения. Например, макросы Лиспа, препроцессор Си или шаблоны С++.
Шаблоны/Generics[править]
Наличие в данном статически типизированном языке инструмента для обобщённого программирования, наподобие templates в C++ или generics в C#.
Поддержка Unicode в идентификаторах[править]
Возможность включения Unicode-символов (например, букв национальных алфавитов) в идентификаторы.
Перегрузка функций[править]
Возможность перегрузки функций/методов по количеству и типам параметров.
Динамические переменные[править]
Возможность создавать переменные, имеющие динамическую область видимости(англ.).
Именованные параметры[править]
Возможность при вызове функции/метода указывать имена параметров и менять их местами.
Значения параметров по умолчанию[править]
Возможность при вызове функции/метода опускать некоторые параметры, чтобы при этом подставлялось значение по умолчанию, указанное при определении функции.
Локальные функции[править]
Возможность определять локальную функцию внутри другой функции/метода. Подразумевается возможность использовать внутри локальной функции локальные переменные из внешнего блока.
Сопоставление с образцом[править]
Наличие сопоставления с образцом.
Контрактное программирование[править]
Возможность задавать пред- и постусловия для методов и инварианты для классов.
См. также[править]
Ссылки[править]
- Эволюция современных языков программирования | Мир ПК | Издательство «Открытые системы»(рус.) osp.ru
- Компьютерра: Java vs .NET(рус.) computerra
- Таблица сравнения языков от создателей D (+ обсуждение на RSDN)
- Созданная на её основе поклонниками других языков более объемлющая таблица(англ.)
- Microbenchmarking C++, C#, and Java(англ.)