Apa perbedaan antara bahasa yang sangat diketik dan bahasa yang diketik secara statis?

Jawaban:

543

Apa perbedaan antara bahasa yang sangat diketik dan bahasa yang diketik secara statis?

Bahasa yang diketik secara statis memiliki sistem tipe yang diperiksa pada waktu kompilasi oleh implementasi (kompiler atau juru bahasa). Pemeriksaan tipe menolak beberapa program, dan program yang lulus pemeriksaan biasanya disertai dengan beberapa jaminan; misalnya, kompilator menjamin untuk tidak menggunakan instruksi aritmatika integer pada angka floating-point.

Tidak ada kesepakatan nyata tentang apa arti "sangat diketik", meskipun definisi yang paling banyak digunakan dalam literatur profesional adalah bahwa dalam bahasa "sangat diketik", tidak mungkin bagi pemrogram untuk mengatasi batasan yang diberlakukan oleh sistem tipe . Istilah ini hampir selalu digunakan untuk menggambarkan bahasa yang diketik secara statis.

Statis vs dinamis

Kebalikan dari yang diketik secara statis adalah "diketik secara dinamis", yang artinya

  1. Nilai yang digunakan pada saat run diklasifikasikan ke dalam jenis.
  2. Ada batasan tentang bagaimana nilai tersebut dapat digunakan.
  3. Ketika pembatasan dilanggar, pelanggaran dilaporkan sebagai jenis kesalahan (dinamis).

Misalnya, Lua , bahasa yang diketik secara dinamis, memiliki tipe string, tipe angka, dan tipe Boolean. Dalam Lua setiap nilai milik tepat satu jenis, tetapi ini bukan persyaratan untuk semua bahasa yang diketik secara dinamis. Di Lua, diperbolehkan untuk menggabungkan dua string, tetapi tidak diizinkan untuk menggabungkan string dan Boolean.

Kuat vs lemah

Kebalikan dari "sangat diketik" adalah "diketik dengan lemah", yang berarti Anda dapat bekerja di sekitar sistem tipe. C diketik dengan lemah karena semua tipe pointer dapat dikonversi ke tipe pointer lainnya hanya dengan casting. Pascal dimaksudkan untuk diketik dengan kuat, tetapi kekhilafan dalam desain (catatan varian tidak bertanda) memperkenalkan celah ke dalam sistem tipe, jadi secara teknis itu diketik dengan lemah. Contoh bahasa yang benar-benar sangat diketik termasuk CLU, Standard ML, dan Haskell. Standar ML sebenarnya telah mengalami beberapa revisi untuk menghilangkan celah dalam sistem tipe yang ditemukan setelah bahasa tersebut digunakan secara luas.

Apa yang sebenarnya terjadi di sini?

Secara keseluruhan, ternyata tidak terlalu berguna untuk berbicara tentang "kuat" dan "lemah". Apakah suatu sistem tipe memiliki celah lebih kurang penting daripada jumlah dan sifat pasti lubang itu, seberapa besar kemungkinan mereka muncul dalam praktik, dan apa konsekuensi dari mengeksploitasi celah. Dalam prakteknya, yang terbaik untuk menghindari istilah "kuat" dan "lemah" sama sekali , karena

  • Amatir sering mengacaukannya dengan "statis" dan "dinamis".

  • Rupanya "pengetikan lemah" digunakan oleh beberapa orang untuk berbicara tentang kelanjutan relatif atau tidak adanya konversi tersirat.

  • Profesional tidak dapat menyetujui secara tepat apa arti istilah tersebut.

  • Secara keseluruhan Anda tidak akan memberi tahu atau mencerahkan audiens Anda.

Kebenaran yang menyedihkan adalah bahwa ketika datang untuk mengetik sistem, "kuat" dan "lemah" tidak memiliki kesepakatan universal tentang makna teknis. Jika Anda ingin mendiskusikan kekuatan relatif dari sistem tipe, lebih baik untuk membahas dengan tepat jaminan apa yang ada dan tidak disediakan. Misalnya, pertanyaan yang bagus untuk ditanyakan adalah ini: "apakah setiap nilai dari suatu jenis (atau kelas) dijamin telah dibuat dengan memanggil salah satu konstruktor tipe itu?" Dalam C jawabannya adalah tidak. Di CLU, F #, dan Haskell itu ya. Untuk C ++ saya tidak yakin — saya ingin tahu.

Sebaliknya, pengetikan statis berarti bahwa program diperiksa sebelum dieksekusi , dan suatu program mungkin ditolak sebelum dimulai. Pengetikan dinamis berarti bahwa jenis nilai diperiksa selama eksekusi, dan operasi yang diketik dengan buruk dapat menyebabkan program berhenti atau menandakan kesalahan pada waktu berjalan. Alasan utama untuk pengetikan statis adalah untuk mengesampingkan program yang mungkin memiliki "kesalahan tipe dinamis".

Apakah yang satu menyiratkan yang lain?

Pada tingkat yang bertele-tele, tidak, karena kata "kuat" tidak benar-benar berarti apa-apa. Namun dalam praktiknya, orang hampir selalu melakukan satu dari dua hal:

  • Mereka (salah) menggunakan "kuat" dan "lemah" untuk berarti "statis" dan "dinamis", dalam hal ini mereka (salah) menggunakan "sangat diketik" dan "diketik secara statis" secara bergantian.

  • Mereka menggunakan "kuat" dan "lemah" untuk membandingkan properti dari sistem tipe statis. Sangat jarang mendengar seseorang berbicara tentang sistem tipe dinamis "kuat" atau "lemah". Kecuali untuk FORTH, yang tidak benar-benar memiliki sistem tipe apa pun, saya tidak bisa memikirkan bahasa yang diketik secara dinamis di mana sistem tipe dapat ditumbangkan. Berdasarkan definisi, pemeriksaan-pemeriksaan tersebut dilakukan dalam mesin eksekusi, dan setiap operasi diperiksa kewarasannya sebelum dieksekusi.

Either way, jika seseorang menyebut bahasa "sangat diketik", orang itu sangat mungkin berbicara tentang bahasa yang diketik secara statis.

Norman Ramsey
sumber
3
@ Adam: Jelas tidak cukup benar untuk di-upgrade :) Karena jawaban Cletus mengandung begitu banyak kesalahpahaman (walaupun saya mengedit yang terburuk dari mereka), saya merasa terdorong untuk mengeja semuanya dengan kata-kata satu suku kata ...
Norman Ramsey
1
Yah saya terbalik Anda :) Bahkan kata "kompilasi" tidak jelas dengan VM saat ini menjalankan bahasa yang dinamis. Secara teknis Java dan C # dikompilasi dua kali (JIT) dan keduanya melakukan beberapa jenis analisis. Bahasa seperti Javascript yang berjalan di .NET vm mungkin lebih aman karena VM.
Adam Gent
2
Saya sangat bingung sekarang! Oke, gladiator hebat di arena, bisakah jiwa yang miskin seperti saya pergi dengan pemahaman sederhana berikut? 1.Static: Nilai dikaitkan dengan jenis selama waktu kompilasi dan bukan waktu berjalan. 2. Dinamik: Nilai terkait dengan jenis selama runtime, maka jenis nilai dapat berubah selama runtime ~ jadi lebih rentan untuk mengetik masalah casting terkait selama runtime. 3. Kuat / lemah: Lupakan! Ini bukan istilah teknis dan hanya nomenklatur yang buruk. Itu tergantung pada konteks apa yang dibicarakan. Bisakah saya melanjutkan hidup saya dengan pemahaman sederhana ini? :(
Saurabh Patil
"Apakah setiap nilai dari tipe (atau kelas) tertentu dijamin telah dibuat dengan memanggil salah satu konstruktor tipe itu?" Dalam C jawabannya adalah tidak. Bisakah seseorang memberikan contoh situasi di mana ini terjadi di C? Saya kira itu melibatkan casting pointer ke struct?
corazza
Mengetik Kuat dan Lemah: tidak ada klasifikasi seperti itu.
Raúl
248

Ini sering disalahpahami jadi izinkan saya menjernihkannya.

Pengetikan Statis / Dinamis

Pengetikan statis adalah tempat jenis terikat ke variabel . Jenis diperiksa pada waktu kompilasi.

Pengetikan dinamis adalah tempat jenis itu terikat dengan nilai . Jenis diperiksa pada saat dijalankan.

Jadi di Jawa misalnya:

String s = "abcd";

sakan "selamanya" menjadi String. Selama hidupnya mungkin menunjuk ke yang berbeda String(karena smerupakan referensi di Jawa). Mungkin memiliki nullnilai tetapi tidak akan pernah merujuk ke Integeratau List. Itu pengetikan statis.

Dalam PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

Itu pengetikan dinamis.

Mengetik Kuat / Lemah

(Edit lansiran!)

Mengetik dengan kuat adalah frasa tanpa makna yang disepakati secara luas. Sebagian besar programmer yang menggunakan istilah ini untuk mengartikan sesuatu selain dari pengetikan statis menggunakannya untuk menyiratkan bahwa ada jenis disiplin yang ditegakkan oleh kompiler. Misalnya, CLU memiliki sistem tipe kuat yang tidak memungkinkan kode klien untuk membuat nilai tipe abstrak kecuali dengan menggunakan konstruktor yang disediakan oleh tipe tersebut. C memiliki sistem tipe yang agak kuat, tetapi dapat "ditumbangkan" ke tingkat tertentu karena suatu program selalu dapat memberikan nilai dari satu tipe pointer ke nilai dari tipe pointer lain. Jadi misalnya, dalam C Anda dapat mengambil nilai yang dikembalikan oleh malloc()dan dengan riang menyerahkannya FILE*, dan kompilator tidak akan mencoba menghentikan Anda — atau bahkan memperingatkan Anda bahwa Anda melakukan sesuatu yang cerdik.

(Jawaban awal mengatakan sesuatu tentang nilai "tidak mengubah jenis pada waktu berjalan". Saya sudah tahu banyak perancang bahasa dan penulis kompiler dan belum tahu yang berbicara tentang mengubah nilai jenis saat dijalankan, kecuali mungkin beberapa penelitian yang sangat maju dalam jenis sistem, di mana ini dikenal sebagai "masalah pembaruan yang kuat".)

Pengetikan yang lemah menyiratkan bahwa kompiler tidak memberlakukan disket pengetikan, atau mungkin bahwa penegakan dapat dengan mudah ditumbangkan.

Asli dari jawaban ini mengaitkan pengetikan yang lemah dengan konversi implisit (kadang-kadang juga disebut "promosi implisit"). Misalnya, di Jawa:

String s = "abc" + 123; // "abc123";

Ini adalah kode yang merupakan contoh dari promosi implisit: 123 secara implisit dikonversi ke string sebelum digabungkan dengan "abc". Dapat dikatakan kompiler Java menulis ulang kode itu sebagai:

String s = "abc" + new Integer(123).toString();

Pertimbangkan masalah PHP klasik "dimulai dengan":

if (strpos('abcdef', 'abc') == false) {
  // not found
}

Kesalahan di sini adalah bahwa strpos()mengembalikan indeks pertandingan, menjadi 0. 0 dipaksa menjadi boolean falsedan dengan demikian kondisinya benar. Solusinya adalah menggunakan ===alih-alih ==menghindari konversi implisit.

Contoh ini menggambarkan bagaimana kombinasi konversi implisit dan pengetikan dinamis dapat menyesatkan programmer.

Bandingkan dengan Ruby:

val = "abc" + 123

yang merupakan kesalahan runtime karena di Ruby objek 123 tidak secara implisit dikonversi hanya karena kebetulan diteruskan ke suatu +metode. Di Ruby, programmer harus membuat konversi eksplisit:

val = "abc" + 123.to_s

Membandingkan PHP dan Ruby adalah ilustrasi yang bagus di sini. Keduanya adalah bahasa yang diketik secara dinamis tetapi PHP memiliki banyak konversi implisit dan Ruby (mungkin mengejutkan jika Anda tidak terbiasa dengan itu) tidak.

Statis / Dinamis vs Kuat / Lemah

Intinya di sini adalah bahwa sumbu statis / dinamis tidak tergantung pada sumbu kuat / lemah. Orang membingungkan mereka mungkin sebagian karena pengetikan yang kuat vs yang lemah tidak hanya kurang jelas didefinisikan, tidak ada konsensus nyata tentang apa yang dimaksud dengan kuat dan lemah. Karena alasan ini, pengetikan kuat / lemah jauh lebih menyerupai warna abu-abu daripada hitam atau putih.

Jadi untuk menjawab pertanyaan Anda: cara lain untuk melihat ini yang sebagian besar benar adalah dengan mengatakan bahwa pengetikan statis adalah tipe keamanan waktu kompilasi dan pengetikan yang kuat adalah tipe keamanan runtime.

Alasan untuk ini adalah bahwa variabel dalam bahasa yang diketik secara statis memiliki tipe yang harus dideklarasikan dan dapat diperiksa pada waktu kompilasi. Bahasa yang sangat diketik memiliki nilai yang memiliki tipe pada waktu berjalan, dan sulit bagi programmer untuk menumbangkan sistem tipe tanpa pemeriksaan dinamis.

Tetapi penting untuk memahami bahwa suatu bahasa bisa Statis / Kuat, Statis / Lemah, Dinamis / Kuat atau Dinamis / Lemah.

cletus
sumber
Alih-alih mengatakan $ s adalah bilangan bulat atau string, akan lebih baik jika Anda mengatakan jenis dikaitkan dengan "abcd" atau 1234 tidak dengan variabel $ s.
Srinivas Reddy Thatiparthy
Jawaban yang sangat bagus dengan contoh-contoh yang jelas. Namun, saya pikir itu tidak sepenuhnya mengatasi kebingungan MENGAPA orang bertanya tentang kuat / statis sebagai pasangan konsep kembar. Misalnya, kata-kata OP tentang "apakah pengetikan statis MUNGKIN mengetik dengan kuat?" Jawaban Anda menekankan kemandirian mereka. Untuk melanjutkan klarifikasi mengapa yang kuat sering dipasangkan dengan statis, jawaban sebelumnya Norman Ramsey sangat baik: stackoverflow.com/questions/376611/…
JasDev
1
"abc" + 123adalah kesalahan runtime , bukan kesalahan kompilasi di ruby. Jika itu adalah kesalahan kompilasi, ruby ​​akan diketik secara statis.
sepp2k
Contoh pengetikan yang lemah perlu ditingkatkan (lihat jawaban saya) tetapi pemformatan yang bagus.
Adam Gent
Dalam opion saya kuat vs typgin lemah adalah ini: Kuat: "c" + True = kesalahan runtime atau kompilasi waktu kesalahan. Lemah: "c" + True = "b" atau "d" karena semuanya diperlakukan sebagai byte mentah. Kuat: C #, Ruby, C ++ Lemah: Majelis, C (karena pointer batal)
Jonathan Allen
17

Keduanya adalah kutub pada dua sumbu yang berbeda:

  • diketik dengan kuat vs. diketik dengan lemah
  • diketik secara statis vs. diketik secara dinamis

Berarti sangat diketik , a tidak akan secara otomatis dikonversi dari satu jenis ke jenis lainnya. Ketik yang lemah adalah kebalikannya: Perl dapat menggunakan string seperti "123"dalam konteks numerik, dengan secara otomatis mengubahnya menjadi int 123. Bahasa yang sangat diketik seperti python tidak akan melakukan ini.

Berarti diketik secara statis , kompilator menggambarkan tipe setiap variabel pada waktu kompilasi. Bahasa yang diketik secara dinamis hanya mengetahui jenis variabel saat runtime.

Daren Thomas
sumber
6
Saya harus tidak setuju. Bahasa yang sangat diketik adalah bahasa yang tahu jenis apa yang ada saat runtime. Bahasa yang diketik dengan lemah adalah bahasa yang tidak suka Assembly. Contoh Anda ada pada sumbu ketiga, "konversi implisit vs eksplisit".
Jonathan Allen
1
Sebenarnya normal saya setuju Jonathan tetapi Anda tidak harus memiliki tipe yang tersedia saat runtime untuk diketik dengan kuat jika Anda melakukan analisis statis lengkap dan tidak mengizinkan casting. (lihat jawaban saya yang diedit).
Adam Gent
1
Python adalah contoh dari bahasa yang diketik secara dinamis dan sangat diketik
MaRoBet
13

Diketik dengan kuat berarti ada pembatasan antara konversi antar jenis. Ketikan statis berarti bahwa jenisnya tidak dinamis - Anda tidak dapat mengubah jenis variabel setelah variabel dibuat.

Svetlozar Angelov
sumber
Untuk mendemonstrasikan ini: Dalam bahasa yang diketik sangat, Anda tidak dapat membandingkan "5" == 5 dan menjadikannya benar: String bukan bilangan bulat. Jika ingatanku, sebagian besar bahasa skrip modern diketik secara dinamis. Tcl / Tk, namun diketik dengan lemah - Semuanya dapat diperlakukan sebagai string.
Little Bobby Tables
Bobby, dalam bahasa yang diketik dengan lemah "5" == 5 dibaca sebagai 0x35 == 0x05. Atau dengan kata lain, semuanya diperlakukan sebagai byte mentah.
Jonathan Allen
Saya harus tidak setuju dengan Anda berdua. Ambil Lua; Anda dapat membandingkan "5" == 5 dan hasilnya akan kembali salah, namun konversi cepat dapat dilakukan dengan membuka "5" + 0.
RCIX
12

Pemaksaan data tidak berarti mengetik dengan lemah karena terkadang gula sintaksisnya:

Contoh di atas Jawa diketik dengan lemah karena

String s = "abc" + 123;

Bukan contoh yang diketik dengan lemah karena benar-benar melakukan:

String s = "abc" + new Integer(123).toString()

Pemaksaan data juga tidak diketik dengan lemah jika Anda membangun objek baru. Java adalah contoh yang sangat buruk untuk mengetik yang lemah (dan bahasa apa pun yang memiliki refleksi yang baik kemungkinan besar tidak akan diketik dengan lemah). Karena runtime bahasa selalu tahu apa jenisnya (pengecualian mungkin tipe asli).

Ini tidak seperti C. C adalah salah satu contoh terbaik dari yang diketik dengan lemah. Runtime tidak tahu apakah 4 byte adalah integer, struct, pointer atau 4 karakter.

Runtime bahasa benar-benar mendefinisikan apakah itu diketik dengan lemah atau tidak, itu hanya pendapat yang benar-benar adil.

SUNTING: Setelah berpikir lebih jauh, ini tidak selalu benar karena runtime tidak harus memiliki semua jenis yang direvisi dalam sistem runtime menjadi sistem yang diketik dengan kuat. Haskell dan ML memiliki analisis statis lengkap sehingga mereka dapat berpotensi informasi tipe ommit dari runtime.

Adam Gent
sumber
B mungkin contoh yang lebih baik, jika sedikit kurang dikenal.
Tom Hawtin - tackline
Javascript juga jenis yang agak lemah tetapi karena ada beberapa jenis dan karena Anda tidak dapat benar-benar membangun jenis baru.
Adam Gent
10

Jawaban sudah diberikan di atas. Mencoba membedakan antara konsep kuat vs minggu dan konsep statis vs dinamis.

Apa yang diketik dengan Kuat VS yang diketik dengan lemah?

Sangat Diketik: Tidak akan secara otomatis dikonversi dari satu jenis ke yang lain

Di Go atau Python seperti bahasa yang sangat diketik "2" + 8 akan memunculkan kesalahan ketik, karena mereka tidak mengizinkan "ketik paksaan".

Diketik dengan lemah (secara longgar): Akan secara otomatis dikonversi ke satu jenis dengan yang lain: Bahasa yang diketik dengan lemah seperti JavaScript atau Perl tidak akan menghasilkan kesalahan dan dalam hal ini JavaScript akan menghasilkan '28' dan perl akan menghasilkan 10.

Contoh Perl:

my $a = "2" + 8;
print $a,"\n";

Simpan ke main.pl dan jalankan perl main.pldan Anda akan mendapatkan output 10.

Apa itu tipe Static VS Dynamic?

Dalam pemrograman, pemrogram mendefinisikan pengetikan statis dan pengetikan dinamis sehubungan dengan titik di mana jenis variabel diperiksa. Bahasa yang diketik secara statis adalah yang di mana pemeriksaan tipe dilakukan pada waktu kompilasi, sedangkan bahasa yang diketik dinamis adalah yang di mana pemeriksaan tipe dilakukan pada saat run-time.

  • Statis: Jenis diperiksa sebelum waktu berjalan
  • Dinamis: Jenis diperiksa dengan cepat, selama eksekusi

Apa ini artinya?

In Go memeriksa cek yang diketik sebelum waktu berjalan (pemeriksaan statis). Ini berarti tidak hanya menerjemahkan dan mengetikkan kode pemeriksaan yang dijalankan, tetapi akan memindai semua kode dan jenis kesalahan akan dilempar sebelum kode dijalankan. Sebagai contoh,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Simpan file ini di main.go dan jalankan, Anda akan mendapatkan kompilasi pesan gagal untuk ini.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

Tapi kasus ini tidak berlaku untuk Python. Misalnya blok kode berikut akan mengeksekusi untuk panggilan foo pertama (2) dan akan gagal untuk panggilan foo kedua (0) Itu karena Python diketik secara dinamis, itu hanya menerjemahkan dan mengetikkan kode pemeriksaan yang dijalankannya. Blok lain tidak pernah dijalankan untuk foo (2), jadi "2" + 8 bahkan tidak pernah melihat dan untuk foo (0) panggilan itu akan mencoba mengeksekusi blok itu dan gagal.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

Anda akan melihat output berikut

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects
Balkrishna
sumber
8

Satu tidak menyiratkan yang lain. Untuk bahasa yang diketik secara statis itu berarti jenis semua variabel diketahui atau disimpulkan pada waktu kompilasi.

Sebuah kuat bahasa diketik tidak memungkinkan Anda untuk menggunakan satu jenis dengan yang lain. C adalah bahasa yang diketik dengan lemah dan merupakan contoh yang baik dari apa yang tidak diizinkan oleh bahasa yang diketik dengan kuat. Dalam C Anda bisa melewatkan elemen data dari tipe yang salah dan tidak akan mengeluh. Dalam bahasa yang sangat diketik Anda tidak bisa.

Joe Cannatti
sumber
7

Pengetikan yang kuat mungkin berarti bahwa variabel memiliki tipe yang terdefinisi dengan baik dan bahwa ada aturan ketat tentang menggabungkan variabel dari tipe yang berbeda dalam ekspresi. Misalnya, jika A adalah bilangan bulat dan B adalah pelampung, maka aturan ketat tentang A + B mungkin bahwa A dilemparkan ke pelampung dan hasilnya dikembalikan sebagai pelampung. Jika A adalah bilangan bulat dan B adalah string, maka aturan yang ketat mungkin bahwa A + B tidak valid.

Mengetik statis mungkin berarti bahwa jenis ditugaskan pada waktu kompilasi (atau yang setara untuk bahasa yang tidak dikompilasi) dan tidak dapat berubah selama eksekusi program.

Perhatikan bahwa klasifikasi ini tidak saling eksklusif, memang saya berharap mereka sering terjadi bersama. Banyak bahasa yang sangat diketik juga diketik secara statis.

Dan perhatikan bahwa ketika saya menggunakan kata 'mungkin' itu karena tidak ada definisi istilah yang diterima secara universal. Seperti yang sudah Anda lihat dari jawaban sejauh ini.

Tanda Kinerja Tinggi
sumber