Apakah jenis tertentu masih diperlukan?

20

Satu hal yang terjadi pada saya tempo hari, adalah jenis tertentu masih diperlukan atau warisan yang menahan kita. Yang saya maksud adalah: apakah kita benar-benar membutuhkan pendek, int, panjang, bigint dll.

Saya mengerti alasannya, variabel / objek disimpan dalam memori, memori perlu dialokasikan dan oleh karena itu kita perlu tahu seberapa besar variabel dapat. Tapi sungguh, seharusnya bahasa pemrograman modern tidak dapat menangani "tipe adaptif", yaitu, jika sesuatu hanya pernah dialokasikan dalam rentang shortint, ia menggunakan lebih sedikit byte, dan jika sesuatu tiba-tiba dialokasikan dalam jumlah yang sangat besar memori dialokasikan sesuai dengan contoh khusus itu.

Float, nyata dan ganda agak sulit karena jenisnya tergantung pada presisi yang Anda butuhkan. Namun string harus dapat mengambil lebih sedikit memori upp dalam banyak kasus (dalam. Net) di mana sebagian besar ascii digunakan tetapi string selalu mengambil dua kali lipat memori karena pengkodean unicode.

Satu argumen untuk tipe tertentu mungkin adalah bahwa itu bagian dari spesifikasi, yaitu misalnya variabel tidak boleh lebih besar dari nilai tertentu sehingga kami mengaturnya ke shortint. Tetapi mengapa tidak memiliki batasan tipe saja? Akan jauh lebih fleksibel dan kuat untuk dapat mengatur rentang dan nilai yang diizinkan pada variabel (dan properti).

Saya menyadari masalah besar dalam pembenahan arsitektur tipe karena sangat terintegrasi dengan perangkat keras yang mendasarinya dan hal-hal seperti serialisasi mungkin memang rumit. Tapi dari perspektif pemrograman itu harus hebat bukan?

Homde
sumber
6
PHP, Ruby, Perl dan lainnya tidak mengharuskan Anda untuk menyatakan jenis variabel. Lingkungan memikirkannya untuk Anda.
FrustratedWithFormsDesigner
7
String Unicode tidak harus mengambil memori tambahan saat mereka digunakan hanya untuk ASCII (UTF-8).
2
Tetapi ada perbedaan antara varian dan tipe adaptif IMO. Varian tidak diketik sama sekali tetapi diketik saat ditugaskan, sedangkan tipe adaptif akan diketik, tetapi lebih longgar. (dan saya suka konsep batasan tipe)
Homde
Ini mengingatkan saya pada proyek ini: tom.lokhorst.eu/media/…
LennyProgrammers
4
Bagaimana dengan Ada? type hour is range 0 .. 23;
mouviciel

Jawaban:

12

Saya benar-benar percaya ini adalah masalahnya. Kendala semantik bernilai lebih dari kendala implementasi. Khawatir tentang ukuran sesuatu terasa seperti khawatir tentang kecepatan sesuatu ketika pemrograman berorientasi objek terjadi.

Itu belum menggantikan pemrograman kritis kinerja. Itu hanya membuat pemrograman kritis non-kinerja lebih produktif.

Mark Canlas
sumber
1
Lihat Kontrak Kode di .NET 4.0.
Steven Jeuris
+1 Dalam hal penyimpanan / transmisi data (mis. Jaringan), kendala adalah hal mendasar untuk memaksimalkan efisiensi protokol / implementasi. Juga, ada banyak tanah yang bisa diperoleh jika koleksi yang diketik tersedia. Selain itu, aman untuk mengasumsikan bahwa efisiensi dapat mengambil kursi belakang (terutama jika itu mengurangi kemungkinan kesalahan semantik).
Evan Plaice
9

Tipe adaptif berarti logika untuk melakukan adaptasi, berarti bekerja pada saat runtime untuk menjalankan logika itu (templating dan compile-time akan membutuhkan tipe spesifik, tipe inferensi menjadi kasus khusus di mana Anda mendapatkan yang terbaik dari dua dunia). Pekerjaan ekstra itu bisa ok di lingkungan di mana kinerja tidak kritis, dan sistem menjaga ukuran yang masuk akal. Di lingkungan lain tidak (sistem embedded adalah satu, di mana Anda kadang-kadang harus menggunakan tipe integer 32/64bits untuk kinerja CPU, dan tipe integer 8/16bit untuk optimasi cadangan memori statis).

Bahkan bahasa tujuan umum yang mendukung pengikatan terlambat (resolusi jenis saat runtime, seperti VB6) cenderung mempromosikan pengetikan yang kuat sekarang (VB.NET), karena kinerja yang dulu muncul saat pengikatan terlambat disalahgunakan, dan karena Anda sering berakhir dengan kode jelek ketika jenis tidak eksplisit ( Referensi / Profesional Refactoring dalam Visual Basic - Danijel Arsenovski ).

Matthieu
sumber
Silakan tentukan "pengetikan otomatis".
@delnan: mengganti pengetikan otomatis dengan pengikatan lambat yang saya maksudkan :)
Matthieu
Ada banyak bahasa tujuan umum yang menyelesaikan tipe saat runtime, Common Lisp untuk menyebutkan hanya satu. (Untuk tujuan kinerja, Anda dapat mendeklarasikan tipe dalam Common Lisp, sehingga Anda dapat melakukannya hanya di bagian yang kritis terhadap kinerja.)
David Thornley
@ David Thornley: "menegakkan" pengetikan yang kuat mungkin terlalu kuat, "mempromosikan" akan lebih tepat, memperbarui jawaban saya yang sesuai. Bahasa yang memungkinkan Anda memilih di antara kedua jenis ikatan tergantung pada situasinya tentu lebih baik daripada dipaksa dalam satu atau lain cara. Terutama ketika tidak melakukan pemrograman tingkat rendah, dan fokus pada logika.
Matthieu
4

Kesederhanaan, Memori, dan Kecepatan Ketika saya mendeklarasikan variabel, memori untuk variabel tersebut dialokasikan dalam satu blok. Untuk mendukung variabel yang tumbuh secara dinamis, saya harus menambahkan konsep memori yang tidak bersebelahan dengan variabel tersebut (baik itu atau menyimpan blok terbesar yang dapat diwakili oleh variabel tersebut). Memori yang tidak bersebelahan akan mengurangi kinerja saat penugasan / pengambilan. Mengalokasikan yang terbesar mungkin akan sia-sia dalam skenario di mana saya hanya membutuhkan satu byte tetapi cadangan sistem lama.

Pikirkan pengorbanan antara array dan vektor (atau daftar tertaut). Dengan sebuah array, mencari posisi tertentu adalah masalah sederhana untuk mendapatkan posisi awal dan menggeser penunjuk memori x spasi untuk menemukan posisi baru di memori. Anggap int sebagai bit [32] membaca int melibatkan berjalan melalui array itu untuk mendapatkan semua nilai bit.

Untuk membuat tipe angka dinamis, Anda harus mengubahnya dari array bit ke vektor bit. Membaca nomor dinamis Anda melibatkan pergi ke kepala, mendapatkan bit itu, menanyakan di mana bit berikutnya dalam memori, pindah ke lokasi itu, mendapatkan bit itu, dll. Untuk setiap bit dalam nomor dinamis, Anda melakukan tiga operasi membaca ( saat ini), baca (alamat berikutnya), pindah (berikutnya). Bayangkan membaca nilai satu juta angka. Itu sejuta operasi ekstra. Ini mungkin tampak tidak signifikan. Tetapi pikirkan sistem (seperti keuangan) di mana setiap milidetik penting.

Keputusan dibuat bahwa meletakkan tanggung jawab pada pengembang untuk memeriksa ukuran dan memvalidasi adalah trade off kecil dibandingkan dengan mempengaruhi kinerja sistem.

Michael Brown
sumber
1
Alternatif lainnya adalah dengan mengimplementasikan angka-angka yang mirip dengan daftar-daftar array di mana array dialokasikan kembali ketika jumlahnya melebihi ukuran saat ini. Anda juga harus memperhitungkan kasus di mana pengguna INGIN meluap ke loop.
Michael Brown
Itu benar, tetapi agak penyederhanaan. Anda bisa menghasilkan struktur array yang lebih efisien, sementara tidak secepat yang diketik secara statis bisa "cukup cepat" untuk sebagian besar kasus. misalnya Anda dapat menyimpan informasi pada blok-blok dari tipe yang berbeda, jika array tidak sepenuhnya bergerigi yang tidak akan mengambil lebih banyak memori atau kinerja. Atau array bisa mengorbankan beberapa memori untuk memiliki semacam indeks. Array bahkan dapat mengoptimalkan sendiri berdasarkan kontennya. Anda masih bisa memiliki opsi untuk mengetikkan ukuran memori melalui batasan jenis jika Anda membutuhkan kinerja.
Homde
Agar adil, itu tidak brutal seperti yang Anda lakukan. Coba jawab saya yang akan datang.
Paul Nathan
3

Jenis khusus diperlukan untuk bahasa dan proyek yang berfokus pada perangkat keras. Salah satu contohnya adalah protokol jaringan on-the-wire.

Tapi mari kita buat - untuk bersenang-senang - jenis varint dalam bahasa seperti C ++. Bangun dari newarray int.

Tidak sulit untuk mengimplementasikan penambahan: hanya xor byte bersama dan periksa bit tinggi: jika ada operasi carry, newdalam byte atas baru dan bawa sedikit lebih. Pengurangan diikuti secara sepele dalam representasi komplemen 2's. (Ini juga dikenal sebagai adder ripple carry).

Penggandaan mengikuti dengan cara yang sama; gunakan menambahkan / bergeser berulang. Seperti biasa, twist yang sebenarnya di ekor Anda adalah pembagian [*].

Apa yang hilang dari Anda saat ini terjadi?

  • Waktu deterministik. Anda memiliki syscall ( new) yang dapat memicu pada titik-titik yang belum tentu dapat dikontrol.

  • Ruang deterministik.

  • Matematika semi-perangkat lunak lambat.

Jika Anda perlu menggunakan bahasa perangkat keras-lapisan dan juga harus beroperasi pada tingkat tinggi (lambat) dan tidak ingin menanamkan mesin scripting, sangat varintmasuk akal. Mungkin ditulis di suatu tempat.

[*] Algoritma matematika perangkat keras Cf untuk cara yang lebih cepat melakukannya - biasanya triknya adalah operasi paralel.

Paul Nathan
sumber
2

Ini pertanyaan yang bagus. Ini menjelaskan mengapa bahasa seperti Python tidak perlu "pendek, int, panjang, bigint dll": integer adalah, well, integer (ada tipe integer tunggal di Python 3), dan tidak memiliki ukuran batas (di luar itu dari memori komputer, tentu saja).

Sedangkan untuk Unicode, pengkodean UTF-8 (yang merupakan bagian dari Unicode) hanya menggunakan satu karakter untuk karakter ASCII, jadi tidak terlalu buruk.

Secara umum, bahasa dinamis tampaknya mengarah ke arah yang Anda sebutkan. Namun, untuk alasan efisiensi, tipe yang lebih terbatas berguna dalam beberapa kasus (seperti program yang harus berjalan cepat). Saya tidak melihat banyak perubahan di masa mendatang, karena prosesor mengatur data dalam byte (atau 2, 4, 8, dll. Byte).

Eric O Lebigot
sumber
1

Berdasarkan teori bahasa, Anda benar. Jenis-jenis harus didasarkan pada serangkaian negara hukum, transformasi yang tersedia untuk negara-negara tersebut, dan operasi yang dapat dilakukan di negara-negara tersebut.

Ini kira-kira yang diberikan oleh OOP pemrograman dalam bentuknya yang khas kepada Anda. Bahkan, di Jawa, Anda secara efektif berbicara tentang BigIntegerdan BigDecimalkelas, yang mengalokasikan ruang berdasarkan berapa banyak yang diperlukan untuk menyimpan objek. (Seperti yang dicatat oleh FrustratedWithFormsDesigner, banyak bahasa tipe skrip bahkan lebih jauh di sepanjang jalur ini dan bahkan tidak memerlukan deklarasi jenis dan akan menyimpan apa pun yang Anda berikan.)

Kinerja masih relevan, bagaimanapun, dan karena itu mahal untuk beralih jenis saat runtime dan karena kompiler tidak dapat menjamin ukuran maksimum variabel pada waktu kompilasi, kami masih memiliki variabel berukuran statis untuk tipe sederhana dalam banyak bahasa.

jprete
sumber
Saya menyadari bahwa semacam pengetikan dinamis / adaptif tampaknya mahal dan kurang berkinerja daripada yang kita miliki sekarang, dan dengan menggunakan kompiler saat ini, tentu saja itu. Tetapi apakah kita 100% yakin bahwa jika Anda membangun bahasa dan kompiler dari bawah ke atas, Anda tidak dapat membuatnya, jika tidak secepat diketik secara statis, setidaknya cepat layak untuk sepadan.
Homde
1
@MKO: Mengapa Anda tidak mencobanya dan melihatnya?
Anon.
1
Ya, Anda dapat membuatnya cepat (tetapi mungkin tidak pernah secepat sistem statis untuk angka). Tetapi bagian "apakah itu sepadan" lebih sulit. Sebagian besar orang bekerja dengan data yang rentangnya cocok dengan nyaman dalam a intatau a double, dan jika tidak, mereka menyadarinya, maka pengukuran nilai dinamis adalah fitur yang tidak perlu mereka bayar.
jprete
Seperti semua programmer tentu saja saya bermimpi suatu hari membuat bahasa saya sendiri;)
Homde
@ jprete: Saya tidak setuju; kebanyakan orang tidak mengetahui kemungkinan hasil antara yang besar. Bahasa seperti itu dapat dan telah dibuat cukup cepat untuk sebagian besar tujuan.
David Thornley
1

Itu tergantung pada bahasanya. Untuk bahasa tingkat yang lebih tinggi seperti Python, Ruby, Erlang, dan semacamnya, Anda hanya memiliki konsep angka integral dan desimal.

Namun, untuk kelas bahasa tertentu yang memiliki jenis ini sangat penting. Ketika Anda menulis kode untuk membaca dan menulis format biner seperti PNG, JPeg, dll. Anda perlu tahu persis berapa banyak informasi yang sedang dibaca sekaligus. Sama dengan penulisan kernel sistem operasi dan driver perangkat. Tidak semua orang melakukan ini, dan dalam bahasa tingkat yang lebih tinggi mereka menggunakan pustaka C untuk melakukan angkat berat secara rinci.

Di short, masih ada tempat untuk jenis yang lebih spesifik, tetapi banyak masalah pengembangan tidak memerlukan ketepatan itu.

Berin Loritsch
sumber
0

Saya baru-baru ini membuat editor logika tangga dan runtime dan saya memutuskan untuk sangat terbatas dengan jenis:

  • Boolean
  • Jumlah
  • Tali
  • Tanggal Waktu

Saya percaya itu membuatnya lebih intuitif bagi pengguna. Ini adalah perubahan radikal dari sebagian besar PLC yang memiliki semua jenis "normal" yang akan Anda lihat dalam bahasa seperti C.

Scott Whitlock
sumber
0

Bahasa pemrograman telah bergerak ke arah itu. Ambil string misalnya. Dalam bahasa lama Anda harus mendeklarasikan ukuran string, seperti PIC X(42)dalam COBOL, DIM A$(42)dalam beberapa versi BASIC, atau [ VAR] CHAR(42)dalam SQL. Dalam bahasa modern Anda hanya memiliki satu stringjenis yang dialokasikan secara dinamis dan tidak perlu memikirkan ukurannya.

Integer berbeda, namun:

Yang saya maksud adalah: apakah kita benar-benar membutuhkan pendek, int, panjang, bigint dll.

Lihatlah Python. Ini digunakan untuk membedakan antara bilangan bulat berukuran mesin ( int) dan ukuran arbitrary ( long). Dalam 3.x yang pertama hilang (yang lama longadalah yang baru int) dan tidak ada yang melewatkannya.

Tetapi masih ada jenis khusus untuk urutan bilangan bulat 8-bit dalam bentuk bytesdan bytearray. Mengapa masing-masing tidak menggunakan a tupleatau listbilangan bulat? Benar, bytesmemang memiliki metode string-seperti ekstra yang tupletidak, tetapi efisiensi pasti banyak hubungannya dengan itu.

Float, nyata dan ganda agak sulit karena jenisnya tergantung pada presisi yang Anda butuhkan.

Tidak juga. Pendekatan "semuanya presisi ganda" sangat umum.

dan04
sumber
1
Mungkin tipe dasar harus menyatakan maksud dasar dari tipe tersebut, yaitu int untuk angka "biasa", dua kali lipat untuk semua "desimal" normal (bukankah ints dapat memiliki desimal meskipun untuk kesederhanaan?) "Uang" untuk bekerja dengan jumlah dan byte untuk bekerja dengan data biner. Batasan jenis yang dideklarasikan melalui atribut dapat memungkinkan untuk mendeklarasikan rentang yang diizinkan, presisi desimal, nullability, dan bahkan nilai yang diizinkan. Akan sangat keren jika Anda dapat membuat jenis yang dapat digunakan kembali dan kustom dengan cara itu
Homde
@konrad: IMHO, alasan bilangan bulat "unsigned" menyebabkan sakit kepala seperti itu di C adalah bahwa mereka kadang-kadang digunakan untuk mewakili angka dan kadang-kadang digunakan untuk mewakili anggota cincin aljabar abstrak pembungkus. Memiliki tipe "ring" dan "unsigned number" yang terpisah dapat memastikan bahwa kode seperti unum64 += ring32a-ring32bakan selalu menghasilkan perilaku yang benar, terlepas dari apakah tipe integer default adalah 16 bit atau 64 [perhatikan bahwa penggunaannya +=sangat penting; ekspresi seperti unum64a = unum64b + (ring32a-ring32b);harus ditolak sebagai ambigu.]
supercat
0

Saya mengerti alasannya, variabel / objek disimpan dalam memori, memori perlu dialokasikan dan oleh karena itu kita perlu tahu seberapa besar variabel dapat. Tapi sungguh, seharusnya bahasa pemrograman modern tidak dapat menangani "tipe adaptif", yaitu, jika sesuatu hanya pernah dialokasikan dalam rentang shortint, ia menggunakan lebih sedikit byte, dan jika sesuatu tiba-tiba dialokasikan dalam jumlah yang sangat besar memori dialokasikan sesuai dengan contoh khusus itu.

Float, nyata dan ganda agak sulit karena jenisnya tergantung pada presisi yang Anda butuhkan. Namun string harus dapat mengambil lebih sedikit memori upp dalam banyak kasus (dalam. Net) di mana sebagian besar ascii digunakan tetapi string selalu mengambil dua kali lipat memori karena pengkodean unicode.

Fortran memiliki sesuatu yang mirip (saya tidak tahu apakah ini yang Anda maksud sebenarnya, karena saya melihat dua pertanyaan yang benar-benar). Misalnya, dalam F90 ke atas Anda tidak perlu secara eksplisit menentukan ukuran tipe , jadi bisa dikatakan. Yang bagus, tidak hanya karena memberi Anda tempat sentral untuk mendefinisikan tipe data Anda, tetapi juga cara portabel untuk mendefinisikannya. NYATA * 4 tidak sama dalam semua implementasi pada semua prosesor (dan dengan prosesor yang saya maksud adalah CPU + compiler), bukan oleh sebuah tugas panjang.

selected_real_kind (p, r) mengembalikan nilai jenis tipe data nyata dengan presisi desimal lebih besar dari setidaknya p digit dan rentang eksponen lebih besar setidaknya r.

Jadi Anda pergi, misalnya;

program real_kinds
integer,parameter :: p6 = selected_real_kind(6)
integer,parameter :: p10r100 = selected_real_kind(10,100) !p is precision, r is range
integer,parameter :: r400 = selected_real_kind(r=400)
real(kind=p6) :: x
real(kind=p10r100) :: y
real(kind=r400) :: z

print *, precision(x), range(x)
print *, precision(y), range(y)
print *, precision(z), range(z)
end program real_kinds

(Saya pikir ini adalah contoh yang cukup jelas).

Masih tidak tahu apakah saya memahami pertanyaan Anda dengan benar, dan ini yang Anda katakan.

Benteng
sumber