Я багато чую, що нові мови програмування динамічно набираються, але що це насправді означає, коли ми говоримо, що мова динамічно набирається та статично набирається?
Я багато чую, що нові мови програмування динамічно набираються, але що це насправді означає, коли ми говоримо, що мова динамічно набирається та статично набирається?
Відповіді:
Мова вводиться статично, якщо тип змінної відомий під час компіляції. Для деяких мов це означає, що ви як програміст повинні вказувати, який тип має кожна змінна (наприклад: Java, C, C ++); інші мови пропонують певну форму виводу типу , можливість системи типів виводити тип змінної (наприклад, OCaml, Haskell, Scala, Kotlin)
Основна перевага тут полягає в тому, що компілятор може проводити всі види перевірки, і тому дуже багато дрібницьких помилок виявляється на дуже ранній стадії.
Приклади: C, C ++, Java, Rust, Go, Scala
Мова динамічно набирається, якщо тип асоціюється зі значеннями часу виконання, а не називається змінними / полями тощо. Це означає, що ви, як програміст, можете писати трохи швидше, тому що вам не доведеться кожного разу вказувати типи (якщо тільки не використовувати статично введену мову з виведенням типу ).
Приклади: Perl, Ruby, Python, PHP, JavaScript
Більшість мов скриптів мають цю особливість, оскільки у будь-якому разі немає компілятора, який би здійснював статичну перевірку типу, але ви можете виявити помилку, пов’язану з неправильним трактуванням типу змінної. На щастя, сценарії невеликі, тому помилок не так багато, щоб заховати.
Більшість динамічно набраних мов дозволяють надавати інформацію про тип, але не вимагають її. Одна мова , який в даний час розробляється, Rascal , приймає гібридний підхід , що дозволяє динамічну типізацію в межах функцій , але примушуючи статичної типізації для функції підпису.
Статично типізовані мови програмування виконують перевірку типів (тобто процес перевірки та виконання обмежень типів) під час компіляції , на відміну від часу виконання .
Динамічно набрані мови програмування перевіряють тип під час виконання , на відміну від часу компіляції .
Прикладами статично набраних мов є: - Java, C, C ++
Прикладами динамічно набраних мов є: Perl, Ruby, Python, PHP, JavaScript
Ось приклад порівняння того, як Python (динамічно набраний) та Go (статично набраний) обробляють помилку типу:
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
Python робить перевірку типу під час виконання, а отже:
silly(2)
Працює ідеально і забезпечує очікуваний результат Hi
. Помилка виникає лише у випадку потрапляння проблемної лінії:
silly(-1)
Виробляє
TypeError: unsupported operand type(s) for +: 'int' and 'str'
тому що відповідний рядок був фактично виконаний.
З іншого боку, перевірка типу під час компіляції:
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
Вищезгадане не компілюється із наступною помилкою:
invalid operation: "3" + 5 (mismatched types string and int)
runhaskell
, наприклад.
Простіше кажучи так: в а типізованих мовах типи змінних є статичними , тобто коли ви встановите змінну типу, ви не можете її змінити. Це тому, що введення пов'язано зі змінною, а не зі значенням, на яке вона посилається.
Наприклад на Java:
String str = "Hello"; //variable str statically typed as string
str = 5; //would throw an error since str is supposed to be a string only
Де з іншого боку: в а типи змінних мов, що динамічно набираються, є динамічними , тобто після встановлення змінної типу ви МОЖЕТЕ її змінити. Це тому, що типізація пов'язана зі значенням, яке воно приймає, а не самою змінною.
Наприклад в Python:
str = "Hello" # variable str is linked to a string value
str = 5 # now it is linked to an integer value; perfectly OK
Отже, найкраще думати про змінні в динамічно набраних мовах як просто загальні вказівники на введені значення.
Підводячи підсумок, введіть опис (або повинен був описати) змінних у мові, а не самої мови. Це можна було б краще використовувати як мову зі статично типізованими змінними порівняно з мовою з динамічно типізованими змінними IMHO.
Статично типізовані мови, як правило, є компільованими мовами, таким чином, компілятори перевіряють типи (має ідеальний сенс правильно? Оскільки типи не можна змінювати пізніше під час виконання).
Динамічно набрані мови, як правило, інтерпретуються, таким чином перевірка типу (якщо така є) відбувається під час виконання під час їх використання. Це, звичайно, приносить певну вартість продуктивності, і є однією з причин, що динамічні мови (наприклад, python, ruby, php) не масштабуються так добре, як типізовані (java, c # тощо). З іншого боку, статично набрані мови мають більшу вартість пуску: зазвичай ви пишете більше коду, складніший код. Але це окупається згодом.
Хороша річ, що обидві сторони - запозичення рис у іншого боку. Набрані мови містять більш динамічні функції, наприклад, генеричні та динамічні бібліотеки в c #, а динамічні мови включають в себе більш перевірку типів, наприклад, анотації типів у python або HACK-варіант PHP, які зазвичай не є основними для мови та можуть бути використані на попит.
Що стосується вибору технології, жодна сторона не має внутрішньої переваги над іншою. Це лише питання переваги, чи хочете ви почати більше контролю або гнучкість. просто виберіть потрібний інструмент для роботи та переконайтесь, що перед тим, як переключитись, перевірте, що є в наявності.
http://en.wikipedia.org/wiki/Type_system
Статичне введення тексту
Кажуть, що мова програмування використовує статичну типізацію, коли перевірка типу виконується під час компіляції, на відміну від часу виконання. При статичному введенні типи асоціюються зі змінними, а не значеннями. Статично типізовані мови включають Ada, C, C ++, C #, JADE, Java, Fortran, Haskell, ML, Pascal, Perl (щодо розрізнення скалярів, масивів, хешів та підпрограм) та Scala. Статичне введення тексту є обмеженою формою перевірки програми (див. Безпеку типу): відповідно, вона дозволяє виявити багато помилок типу на початку циклу розробки. Статичні перевіряючі типи оцінюють лише інформацію про тип, яку можна визначити під час компіляції, але здатні перевірити, чи перевіряються умови для всіх можливих виконання програми, що виключає необхідність повторення перевірок типу щоразу, коли програма виконується. Виконання програми також може бути ефективніше (тобто швидше або зайняття зменшеної пам’яті), опустивши перевірки типу виконання та ввімкнувши інші оптимізації.
Оскільки вони оцінюють інформацію про тип під час компіляції, а отже, бракує інформації про тип, яка доступна лише під час виконання, статичні перевірки типу є консервативними. Вони відхилять деякі програми, які можуть бути добре сприйняті під час виконання, але які не можуть статично визначити, що вони добре набрані. Наприклад, навіть якщо вираз завжди оцінюється як істинне під час виконання, програма, що містить код
if <complex test> then 42 else <type error>
буде відхилено як неправильно введене, оскільки статичний аналіз не може визначити, що інша гілка не буде взята. [1] Консервативна поведінка перевіряючих статичних типів є вигідною, коли нечасто оцінюється на помилкові: Засіб перевірки статичного типу може виявляти помилки типу в рідко використовуваних кодових шляхах. Без статичної перевірки типу навіть тести на покриття коду зі 100% покриттям коду можуть виявити помилки такого типу. Тести на покриття коду можуть виявити помилки такого типу, тому що слід враховувати поєднання всіх місць, де створюються значення, та всіх місць, де використовується певне значення.
Найбільш широко використовувані статично набрані мови формально не є безпечними. У специфікації мови програмування вони мають "лазівки", що дозволяють програмістам писати код, який обходить перевірку, виконану перевіряючим статичним типом, і таким чином вирішує більш широке коло проблем. Наприклад, Java та більшість мов стилю С мають типи покарань, а Haskell має такі функції, як unsafePerformIO: такі операції можуть бути небезпечними під час виконання, оскільки вони можуть спричинити небажану поведінку через неправильне введення значень при запуску програми.
Динамічне введення тексту
Кажуть, що мова програмування динамічно набирається, або просто "динамічно", коли більшість перевірок типу виконується під час виконання на відміну від часу компіляції. У динамічному введенні типи пов'язані зі значеннями, а не змінними. До динамічно набраних мов належать Groovy, JavaScript, Lisp, Lua, Objective-C, Perl (стосовно визначених користувачем типів, але не вбудованих типів), PHP, Prolog, Python, Ruby, Smalltalk та Tcl. У порівнянні зі статичним введенням, динамічне введення тексту може бути більш гнучким (наприклад, дозволяючи програмам генерувати типи та функціональність на основі даних про час виконання), хоча за рахунок менших апріорних гарантій. Це пояснюється тим, що динамічно набрана мова приймає та намагається виконати деякі програми, які можуть бути визнані недійсними за допомогою перевірки статичного типу.
Динамічне введення тексту може призвести до помилок типу виконання - тобто під час виконання значення може мати несподіваний тип, і застосовується нечутлива для цього типу операція. Ця операція може відбутися задовго після того, як була допущена помилка програмування - тобто місця, де неправильний тип даних перейшов у місце, у якому воно не повинно бути. Це ускладнює пошук помилки.
Динамічно типізовані мовні системи, порівняно зі своїми статично типізованими родичами, роблять менше перевірок «часу компіляції» вихідного коду (але перевірять, наприклад, чи синтаксично програма правильна). Перевірки часу роботи потенційно можуть бути складнішими, оскільки вони можуть використовувати динамічну інформацію, а також будь-яку інформацію, яка була присутня під час компіляції. З іншого боку, перевірки виконання лише стверджують, що умови існують у певному виконанні програми, і ці перевірки повторюються для кожного виконання програми.
Розвиток в динамічно набраних мовах часто підтримується методами програмування, такими як тестування одиниць. Тестування є ключовою практикою у професійній розробці програмного забезпечення та особливо важливо для динамічно набраних мов. На практиці тестування, проведене для забезпечення правильної роботи програми, може виявити набагато ширший спектр помилок, ніж статична перевірка типу, але, навпаки, не може настільки всебічно шукати помилки, які здатні виявити і тестування, і статична перевірка типу. Тестування може бути включено до циклу збирання програмного забезпечення, і в цьому випадку його можна розглядати як перевірку "час компіляції", оскільки користувачеві програми не доведеться вручну виконувати такі тести.
Список літератури
- Пірс, Бенджамін (2002). Типи та мови програмування. MIT Press. ISBN 0-262-16209-1.
myObject[remoteDataName]
. Тоді немає ніякого способу знати, яке саме майно вибере, або навіть якщо воно взагалі є дійсним.
Термін "динамічно набраний", на жаль, вводить в оману. Всі мови набрані статично, а типи - це властивості виразів (а не значень, як думають деякі). Однак деякі мови мають лише один тип. Вони називаються однотипними мовами. Одним із прикладів такої мови є нетипізоване обчислення лямбда.
У нетипізованому обчисленні лямбда всі терміни - це лямбда-терміни, і єдина операція, яку можна виконати на терміні, - це застосувати його до іншого терміна. Отже, всі операції завжди призводять до нескінченної рекурсії або до лямбда-терміну, але ніколи не сигналізують про помилку.
Тим НЕ менше, ми були для посилення Нетипізовані лямбда - обчислення з примітивними числами і арифметичними операціями, то ми могли б виконати безглузді операції, наприклад , додавши два члена лямбда разом: (λx.x) + (λy.y)
. Можна стверджувати, що єдине розумне, що потрібно зробити, - це сигналізувати про помилку, коли це відбувається, але щоб мати змогу це зробити, кожне значення має бути позначене індикатором, який вказує, чи є термін лямбда-терміном чи числом. Потім оператор додавання перевірить, чи дійсно обидва аргументи позначені як числа, а якщо їх немає, подасть сигнал про помилку. Зауважте, що ці теги не є типами, оскільки типи - це властивості програм, а не значення, що створюються цими програмами.
Уніфікована мова, яка це робить, називається динамічно набраною.
Мови, такі як JavaScript, Python та Ruby, є універсальними. Знову ж, typeof
оператор у JavaScript та type
функція в Python мають оманливі назви; вони повертають теги, пов'язані з операндами, а не їх типи. Так само dynamic_cast
в C ++ і instanceof
на Java не роблять перевірки типу.
"Коли перехідний код переведений"
"Коли типи перевіряються"
5 + '3'
є прикладом помилки типу в сильно типізованих мовах, таких як Go і Python, оскільки вони не дозволяють "типу примусу" -> здатності значення змінювати тип у певних контекстах, таких як об'єднання двох типів. Слабо набрані мови, такі як JavaScript, не видають помилку типу (результати в '53'
).
Визначення "Static & Compiled" і "Dynamic & Interpreted" досить схожі ... але пам’ятайте, що "коли типи перевіряються" проти ", коли вихідний код переведений".
Ви отримаєте однотипні помилки незалежно від того, складена чи інтерпретована мова ! Ці поняття потрібно розділити концептуально.
Динамічний, інтерпретований
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
Оскільки Python інтерпретується та динамічно набирається, він лише перекладає та перевіряє код, який він виконує. else
Блок ніколи не виконується, тому 5 + '3'
ніколи навіть НЕ дивився на!
Що робити, якщо він був статично набраний?
Помилка типу буде видана ще до того, як код буде запущений. Він все ще проводить перевірку типу перед часом виконання, навіть якщо його інтерпретують.
Що робити, якщо вона була складена?
else
Блок буде переведений / подивився на перед у час виконання, а тому , що це динамічно типізованих він не видасть помилку! Мови, що динамічно вводяться, не перевіряють типи до виконання, і цей рядок ніколи не виконується.
Статичний, складений
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
Типи перевіряються перед запуском (статичні) і помилка типу негайно виявляється! Типи все-таки перевірятимуться перед запуском, якби його інтерпретували, маючи той самий результат. Якби він був динамічним, він не викидав би жодних помилок, навіть якщо код буде розглянуто під час компіляції.
Скомпільована мова матиме кращі показники під час виконання, якщо вона буде статично введена (проти динамічно); знання типів дозволяє оптимізувати машинний код.
Статично типізовані мови мають кращу продуктивність під час виконання внутрішньо, оскільки не потрібно динамічно перевіряти типи під час виконання (перевіряється перед запуском).
Аналогічно, компільовані мови швидші під час виконання, оскільки код уже перекладено, а не потрібно "інтерпретувати" / перекладати його на ходу.
Зауважте, що як складені, так і статично типізовані мови матимуть затримку перед запуском відповідно для перекладу та перевірки типу.
Статичний набір тексту вводить помилки рано, замість того, щоб їх знаходити під час виконання (особливо корисно для довгих програм). Він більш "суворий" в тому, що він не дозволить вводити помилки в будь-якій точці вашої програми і часто запобігає зміні типів, що надалі захищає від ненавмисних помилок.
num = 2
num = '3' // ERROR
Динамічне введення тексту є більш гнучким, що деякі цінують. Зазвичай це дозволяє змінам типів змінювати типи, що може призвести до несподіваних помилок.
Статично набрані мови : кожна змінна та вираз уже відомі під час компіляції.
(int a;
a може приймати лише цілі значення типів під час виконання)
Приклади: C, C ++, Java
Мови, що динамічно набираються : змінні можуть отримувати різні значення під час виконання, а їх тип визначається під час виконання.
( var a;
а може приймати будь-які значення у процесі виконання)
Приклади: Ruby, Python.
Статистично набрані мови перевірка типу під час компіляції, і тип НЕ може змінюватися. (Не будьте милі з коментарями, що відтворюють тип, створюється нова змінна / посилання).
Перевірка типу мов, що динамічно набираються, під час виконання, а тип змінної CAN може бути змінений під час виконання.
Солодкі та прості визначення, але відповідають потребі: Статично типізовані мови пов'язують тип із змінною на весь його обсяг (Seg: SCALA) Динамічно введені мови прив'язують тип до фактичного значення, на яке посилається змінна.
Статично типізовані мови, такі як C ++, Java та динамічно типізовані мови, такі як Python, відрізняються лише за рівнем виконання типу змінної. Статично типізовані мови мають статичний тип даних для змінної, тут тип даних перевіряється під час компіляції, тому налагодження набагато простіше ... тоді як динамічно вводиться мови не роблять те саме, тип даних перевіряється, який виконує програму, а отже, і налагодження трохи важко.
Більше того, вони мають дуже невелику різницю і можуть бути пов'язані з сильно набраними та слабо набраними мовами. Сильно набрана мова не дозволяє використовувати один тип як інший, наприклад. C і C ++ ... тоді як слабо типізовані мови дозволяють напр. Python
Статично набраний
Типи перевіряються перед запуском, щоб помилки могли бути виявлені раніше.
Приклади = c ++
Динамічно набраний
Види перевіряються під час виконання.
Приклади = Python
Статичні типізовані мови (компілятор вирішує виклики методів та компілює посилання):
Динамічні набрані мови (рішення, прийняті в запущеній програмі):
динамічно набрана мова допомагає швидко прототипувати алгоритми понять, не задумуючись над тим, щоб думати, які змінні типи потрібно використовувати (що є необхідністю в статично набраному мові ).
Статичне введення тексту: такі мови, як Java та Scala, набираються статично.
Змінні повинні бути визначені та ініціалізовані перед їх використанням у коді.
для екс. int x; х = 10;
System.out.println (x);
Динамічне введення тексту: Perl - це динамічна набрана мова.
Змінні не потрібно ініціалізувати до їх використання в коді.
у = 10; використовувати цю змінну в пізнішій частині коду
$
), масив ( @
) та хеш ( %
). Тип змінної в Perl відомий під час компіляції та залишається однаковим протягом усього часу життя змінних.