Чи залежить синтаксис мов програмування від їх реалізації?


12

Хоча, моє запитання може бути абсолютно нерелевантним, але я відчув закономірність між більшістю мов програмування та їх офіційними реалізаціями.

Інтерпретовані (байт-інтерпретовані?) Мови, такі як Python, Lua тощо, зазвичай мають надзвичайно поблажливий і простий синтаксис і, як правило, не мають типу або не вимагають від розробника явно запису змінних типів у вихідний код;

Мови компіляції, такі як C, C ++, Pascal тощо, зазвичай мають суворий синтаксис, зазвичай мають типи і в основному потребують більше коду / часу розробки

Мови, офіційними реалізаціями яких є JIT-Compiled, як Java / C #, як правило, є унікальним компромісом між двома перерахованими вище деякими найкращими можливостями обох.

Деякі з більш сучасних мов програмування, такі як D і Vala (і реалізація Java GNU GJC), можливо, є винятком із цього правила і нагадують синтаксис та особливості мов, компільованих JIT, як Java та C #.

Перше моє запитання: чи це справді актуально? Або це лише збіг обставин, що більшість інтерпретованих мов мають легкий синтаксис, а JIT-Compiled має помірний синтаксис та особливості тощо.

По-друге, якщо це не збіг обставин, то чому так? Як, наприклад, чи можуть деякі функції реалізовані лише мовою програмування, якщо ви, скажімо, JIT-компілюєте її?


@YannisRizos вибачте, це не цитата. Я просто хотів це висвітлити. Я відредагую.
ApprenticeHacker

1
Класно, я хоч і не була цитатою, але це може призвести до того, що відповідачі думають, що це одна, і не намагаються спростувати це (або сліпо погоджуватися з цим) ... Я помітив подібні зразки, але, на жаль, не маю хорошого відповідь.
янніс

@ R.MartinhoFernandes вибачте, я про це не знав. Я відредагую його (знову).
ApprenticeHacker

4
Perl динамічно набирається для визначених користувачем типів, набирається статично відносно розрізнення масивів, хешів, скалярів та підпрограм, а також набирається за допомогою суворого, інтерпретованого та компільованого JIT (не водночас, звичайно) ... Кожен раз, коли хтось намагається щоб зрозуміти мовний дизайн, кидати в якийсь Perl завжди весело ...
yannis

3
Що ви маєте на увазі під "симпатичним поблажливим" проти "суворим синтаксисом"? Всі вони є офіційними мовами, і жодна не запустить вихідний код із синтаксичними помилками.
nikie

Відповіді:


17

Між семантикою та синтаксисом не існує жодного зв'язку. Мови, складені гомоїконікою, як схема, мають досить мінімалістичний синтаксис. Металеві мови низького рівня, такі як Forth, навіть простіші. Деякі дуже строго типізовані складені мови побудовані на тривіальному синтаксисі (подумайте ML, Haskell). OTOH, синтаксис Python дуже важкий, з точки зору ряду синтаксичних правил.

І так, введення тексту не має нічого спільного з синтаксисом, це на стороні семантики мови, якщо тільки це щось не так викривлене, як C ++, де ви навіть не можете проаналізувати, не маючи всієї інформації про введення тексту.

Загальна тенденція полягає в тому, що мови, які розвивалися занадто довго і не містили жодних гарантій дизайну проти відхилень синтаксису, рано чи пізно перетворюються на синтаксичні гидоти.


+1 для того, щоб змусити мене шукати "гомоніксон" ... І за тонкий кивок PHP ...
yannis

1
+1, мови, які розвивалися занадто довго і не містили жодних гарантій дизайну , це стосується також Delphi / Object-Pascal?
ApprenticeHacker

1
@ThomasEding, ти помилився. Ця ж семантика може бути реалізована поверх дуже широкого спектру синтаксичних стилів, навіть із синтаксичною мовою (наприклад, Lisp чи Forth). Той самий синтаксис можна використовувати з дуже великою різноманітністю різної семантики - наприклад, синтаксис виразів C і Verilog майже однаковий, але семантика різко відрізняється.
SK-логіка

1
@ SK-логіка - Тільки тому, що вона є складною і Тюрінг-повною, це не означає, що це не менш велика частина синтаксису програми. Розбір різних мов є завершенням Тьюрінга, що не магічно робить аналіз того, що "не має нічого спільного з синтаксисом". Синтаксис не про "область", це про правила структури висловлювань мовою - не кажучи нічого про те, що означають ці твердження. Перевірка типу та умовиводів працюють на синтаксичних деревах програм, не виконуючи їх - вони визначають речі про структуру програми, нічого не говорячи про ...
Джек

1
@Jack, ти намагаєшся визначити, що таке синтаксис. Немає практичних мов, для яких потрібен аналог Тьюрінга, більшість - це не що інше, як без контексту. І саме тут повинен залишитися синтаксис. Будь ласка, не поширюйте це (вже надто розтягнуте) поняття ніде більше. І я вже згадував про ізоморфізм Керрі-Говарда - мова йде про семантику, далеко поза правилами правильності. Я думаю, що сам термін " type checking" є надзвичайно контрпродуктивним і його не слід вживати, він дуже вводить в оману, не відображає природу типних систем.
SK-логіка

6

Переважно це збіг обставин.

З часом розвиваються мови програмування, а технологія компіляторів та перекладачів вдосконалюється. Ефективність базової обробки (тобто час компіляції, накладні витрати на переклад, час виконання тощо) також має менш важливе значення, оскільки основні обчислювальні платформи зростають у силі.

Синтаксис мови робить впливає - наприклад, Паскаль був дуже ретельно розроблений таким чином , він може використовувати один прохід компілятор - тобто один прохід над джерелом і у вас є excutable машинного коду. Ada з іншого боку не звертала на це уваги, а компілятори Ada, як відомо, важко написати - для більшості потрібен більше одного проходу. (Один дуже хороший компілятор Ada, яким я користувався багато років тому, був 8-прохідний компілятор. Як ви можете собі уявити, це було дуже повільно.)

Якщо ви подивитесь на старі мови, такі як Fortran (компільований) та BASIC (інтерпретований або складений), у них є / були дуже суворі синтаксис та семантичні правила. [У випадку з BASIC, це не векселі старого BASIC, вам потрібно повернутися до цього до оригіналу.]

З іншого боку, дивлячись на інші старі речі, такі як APL (купа задоволення), це було динамічним набором тексту. Він також загалом був інтерпретований, але також міг бути складений.

Синтаксис поблажливий - якщо це означає, що у вас є речі, які є необов'язковими або можна зробити висновок, то це означає, що мова має достатнє багатство, щоб її можна було знищити. Знову ж таки, BASIC мав це багато років тому, коли заява "LET" стала необов'язковою!

Багато ідей, які ви зараз бачите (наприклад, безтипові або динамічні набори тексту), насправді дуже давні - вперше з'явилися в 1970-х або на початку 1980-х. Спосіб їх використання та мови, якими вони користуються, змінювались та зростали. Але принципово, що багато нового є насправді старі речі, одягнені в новий одяг.

Ось декілька прикладів у верхній частині моєї голови:

  • APL: динамічне введення тексту. Взагалі трактується. Походив з 1960-х / 1970-х років.
  • ОСНОВНІ: сильний або динамічний набір тексту. Інтерпретовано або складено. 1970-ті та багато інших.
  • Фортран: сильний набір тексту. Складено. 1960-х років або раніше.
  • Algol68: сильний набір тексту. Складено. 1960-ті.
  • PL / 1: сильний набір тексту. Складено. 1960-ті.
  • Паскаль: сильний набір тексту. Складено. 1970-ті. (Але в 1980-х роках були компілятори P-System, дуже схожі на компілятори JIT!)
  • Деякі реалізації Fortran та інших за допомогою DEC в перші дні були частково складені та частково інтерпретовані.
  • Маленька розмова: динамічне введення тексту. Скомпільований у байт-код, який інтерпретується. 1980-ті.
  • Пролог: більше дивацтв. Функціональний. Складено (Turbo Prolog, хто?). 1980-ті.
  • С: сильний (ха-ха) набір тексту. Складено. 1960-х рр .. сьогодні.
  • Ада: убер-сильний набір тексту. Складено. 1980-ті.
  • Perl: динамічне введення тексту. (Сильний синтаксис). Інтерпретовано. 1990-х (?).

Я міг би продовжувати.

  • Куточок Nitpickers: Багато інтерпретованих мов токенізовано або "байт складений" під час завантаження / читання джерела. Це робить подальшу роботу перекладача набагато простішою. Іноді ви можете зберегти скомпільовану байтом версію коду. Іноді ти не можеш. Її досі інтерпретують.

Оновлення: Тому що я був недостатньо зрозумілий.

Введення тексту може сильно відрізнятися.

Стаціонарне типізування за часом компіляції є загальним (наприклад, C, Ada, C ++, Fortan тощо тощо). Тут декларується ТІНКА ТИПУ, і саме так назавжди.

Можливо також динамічне введення тексту, коли річ підбирає тип, який їй призначений. Наприклад, PHP і деякі початкові BASIC, і APL, де ви призначили цілу величину змінній, і з цього моменту вона була цілим числом. Якщо ви згодом призначили йому рядок, то це був тип рядка. І так далі.

І тоді відбувається друге введення тексту, наприклад, PHP, де ви можете робити справді химерні речі, такі як присвоєння числовому цілому числу (цитується, таким чином, його рядок) змінній, а потім додайте до неї число. (наприклад, "5" + 5 призведе до 10). Це країна химерної, але також часом дуже корисної.

ЯКЩО це функції, вбудовані в мову. Реалізація просто робить це.


13
Сильне введення тексту не є аналогом динамічного набору тексту. Це аналог слабкого набору тексту. Протилежністю динамічного введення є статичне введення тексту: в одному, типи виразів у програмі можуть бути відомі статично (тобто без запуску програми); в іншому типи можна знати лише динамічно (тобто програма повинна бути запущена).
Р. Мартіньо Фернандес

Так, і обидва варіанти BASIC і APL робили це ще в кінці 1970-х. Типи APL не зовсім такі, як ми їх розуміємо сьогодні (це речі, такі як універсально набрані цілі / плавці, але вони також можуть бути векторами, рядками та багатовимірними матрицями).
quick_now

Інтерпретатор Fortran досі широко використовується (див. Cernlib та PAW). А його нащадок, ROOT, побудований на інтерпретаторі C ++.
SK-логіка

Мені не зовсім зрозуміло, наскільки сильне / слабке та статичне / динамічне введення тексту стосується синтаксису, якщо чесно. Але якість відповідей була досить хорошою, тому я просто уникаю голосування. Я б ввів клас C як "статичний / слабкий" (тривіально дивитися на збережене значення, як якщо б це було іншого типу, можливо, неправильне значення).
Ватін

@Vatine - насправді я б сказав, що сильний під час компіляції, неіснуючий під час виконання - якщо ви хочете саме так. Це можна зробити, використовуючи покажчики та їх еквівалент на багатьох мовах. Це можливо навіть у класичному паскалі з використанням варіантів записів, а в Ада за допомогою UNCHECKED_CONVERSION (хоча це і складно, але можливо).
quick_now

2

Я думаю, що навпаки: реалізація залежить від синтаксису. Наприклад, якщо ваш синтаксис дозволяє відображати, то реалізація повинна забезпечувати час виконання, який це підтримує.


@IntermediateHacker: але це в Java, так що я повинен бути дивним
sehe

2

Я, як правило, швидко погоджуюся з тим, що ваші спостереження в основному є результатом історії. Однак, основні міркування зводяться до такого типу:

The more modern a language is, the more comfortable it should be to use.

(Насправді не цитата, а лише моя власна формулювання.) Коли я пишу comfortableтут, я посилаюся на те, що ви закликали best features of both. Точніше, я не хочу виступати за або проти статичного / динамічного набору тексту або строгого / м'якого синтаксису. Натомість важливо спостерігати, як зосереджена увага на розробниках та підвищення рівня їх комфорту при роботі з мовою.

Ось кілька причин, які не були згадані в попередніх відповідях, які можуть дати вам кілька ідей, чому ви спостерігаєте за цими речами (і всі вони базуються на історії розвитку програми затримки):

  • У нас сьогодні сотні затримок програмування. Коли з’являється новий, як він може знайти широку аудиторію? Це головна причина, чому нові мови завжди намагаються підвищити рівень комфорту розробників. Якщо мова може зробити те ж саме, що й старіша, але це може зробити набагато простіше / простіше / елегантніше / тощо. ви можете розглянути можливість фактичного переключення.

  • Крива навчання йде рука об руку. У минулому у нас було небагато мов, і вкладати час, щоб вивчити одну, варто. Навіть якщо це означало б вкласти багато часу. Комфорт знову підвищується, якщо ви придумаєте мову, яку розробники можуть дуже швидко вивчити. Складність будь-якого виду (f.ex., складний синтаксис, що стосується) шкодить цьому, а отже, у нових мовах все більше зменшується.

  • Технологічний прогрес (пряма історична причина тут) несе відповідальність за те, що розробники компіляторів тепер можуть зосередити більше уваги на комфорті розробника. У перші дні ми були щасливі, що змогли створити компілятор взагалі. Однак це часто передбачає введення серйозних обмежень. Коли технологічне ноу-хау зростало, ми знову змогли зняти ці обмеження.

Тож загалом мови мов програмування та компілятори побачили розвиток, подібний до типових додатків для кінцевих користувачів:

  1. Початкова стадія: це класна річ, але технологія кровотоку ледь не змушує її працювати ціною комфорту / зручності використання / що - ні.
  2. Технологічне вдосконалення: ми можемо будувати ці речі міцніше, швидше та простіше.
  3. Фокус звертається до користувача: Аналогічно до руху Web2.0, орієнтованого на досвід користувача, нові мови програмування зосереджуються на перспективі розробника.

(Not a quote really, just my own formulation.)Ну, ви відформатували його як код, а не як
блок-котирування

3
Комфорт явно залежить від смаку (який завжди цілком суб'єктивний). Мова, якою мені найбільше подобається, була розроблена в 1959 році, і я не можу мати справу з деякими мовами, що з'явилися в цьому столітті.
SK-логіка

1
Комфорт також залежить від призначення. Запуск PHP або Prolog на вбудованому мікроконтролері 8K для контролера пральної машини може бути "зручним" для програмування, але й чортово важко насправді зробити його придатним та працювати з прийнятною продуктивністю.
quick_now

0

Дана мова програмування може або не може виставляти або обмежувати достатньо смислової інформації для компілятора, щоб вивести, як звести її до виконуваного коду без доданих рішень виконання ("який тип ця змінна?" Тощо). Деякі мови явно призначені для створення це обмеження є обов'язковим або легко визначити.

Оскільки компілятори стають розумнішими, вони, можливо, зможуть здогадатися або профайлювати достатньо інформації, щоб генерувати виконуваний код для найбільш ймовірного шляху (-ів), навіть для мов, які не були чітко розроблені для того, щоб викрити чи обмежити ці рішення.

Однак мови, де код (evalString ()) може бути створений або введений під час виконання (та інші речі, які компілятор не може вивести і не здогадатися), можуть вимагати, щоб інтерпретатор або компілятор JIT був доступний під час виконання, навіть із спробами попереднього складіть їх.

Раніше мова програмування та її реалізація могли розвиватися так, щоб відповідати деяким апаратним обмеженням, наприклад, чи може інтерпретатор вміститися в 4k або 16k, чи може компілятор закінчити менше хвилини часу процесора. Коли машини швидше стають, стало можливим (повторно) компілювати деякі раніше інтерпретовані програми так швидко, як програміст може натиснути клавішу повернення або інтерпретувати раніше складений вихідний код програми швидше, ніж трохи старше обладнання може запускати оптимізовані компільовані виконувані файли.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.