Spesifik tipler hala gerekli mi?


20

Geçen gün başıma gelen bir şey, hala gerekli olan belirli türler ya da bizi geride tutan bir miras. Demek istediğim: gerçekten kısa, int, uzun, bigint vb.'ye ihtiyacımız var mı?

Akıl yürütmeyi, değişkenlerin / nesnelerin hafızada tutulduğunu, hafızanın tahsis edilmesi gerektiğini ve bu nedenle bir değişkenin ne kadar büyük olabileceğini bilmemiz gerektiğini anlıyorum. Ama gerçekten, modern bir programlama dili "uyarlanabilir türleri" işleyemezse, yani bir şey sadece kısa aralıkta tahsis edilirse, daha az bayt kullanır ve bir şey aniden çok büyük bir sayı tahsis edilirse, bellek tahsis edilir belirli bir örnek için.

Şamandıra, gerçek ve çiftler biraz daha zorlayıcıdır, çünkü tip ihtiyacınız olan hassasiyete bağlıdır. Bununla birlikte, dizeler çoğunlukla ascii'nin kullanıldığı birçok durumda (.Net) daha az bellek alabilir; buth dizeleri, unicode kodlaması nedeniyle her zaman belleği iki katına çıkarır.

Spesifik tipler için bir argüman, spesifikasyonun bir parçası olabileceği, örneğin bir değişkenin belirli bir değerden daha büyük olamaması gerektiği için kısaltmaya ayarladık. Ama neden bunun yerine tip kısıtlamaları yok? Değişkenler (ve özellikler) üzerinde izin verilen aralıklar ve değerler ayarlayabilmek çok daha esnek ve güçlü olacaktır.

Altta yatan donanımla çok sıkı bir şekilde bütünleştiğinden ve serileştirme gibi şeyler gerçekten zor olabileceğinden, tip mimarisini yenilemedeki büyük sorunun farkındayım. Ama bir programlama perspektifinden bakıldığında, harika olmalı değil mi?


6
PHP, Ruby, Perl ve diğerleri değişken türlerini belirtmenizi gerektirmez. Çevre bunu sizin için çözer.
SinirliWithFormsDesigner

7
Unicode dizelerinin yalnızca ASCII için kullanıldıklarında ek bellek alması gerekmez (UTF-8).

2
Ancak varyant ve uyarlanabilir IMO tipleri arasında bir fark vardır. Varyantlar hiç yazılmaz ancak atandığında yazılır, uyarlanabilir türler yazılır ancak daha gevşek olur. (ve tip kısıtlamaları kavramını seviyorum)
Homde

Bu bana bu projeyi hatırlatıyor: tom.lokhorst.eu/media/…
LennyProgrammers

4
Ada ne olacak? type hour is range 0 .. 23;
mouviciel

Yanıtlar:


12

Bunun böyle olduğuna kesinlikle inanıyorum. Anlamsal kısıtlamalar, uygulama kısıtlamalarından daha değerlidir. Bir şeyin büyüklüğü hakkında endişelenmek, nesne yönelimli programlama söz konusu olduğunda bir şeyin hızı hakkında endişe etmek gibi hissettirir.

Performans açısından kritik programlamanın yerini almamıştır. Yalnızca performans dışı kritik programlamayı daha verimli hale getirdi.


1
Check out Kod Sözleşmeleri .NET 4.0.
Steven Jeuris

+1 Veri depolama / iletimi (ör. Ağ oluşturma) söz konusu olduğunda, protokol / uygulamanın verimliliğini en üst düzeye çıkarmak için kısıtlamalar önemlidir. Ayrıca, yazılan koleksiyonlar mevcutsa kazanılacak çok şey vardır. Bunun dışında, verimliliğin arka planda olabileceğini varsaymak güvenlidir (özellikle semantik hata olasılığını azaltırsa).
Evan Plaice

9

Uyarlanabilir türler, uyarlamayı yapmak için mantık anlamına gelir, bu mantığı çalıştırmak için çalışma zamanında çalışmak anlamına gelir (geçici ve derleme zamanı belirli bir tür gerektirir, tür çıkarım iki dünyanın en iyisini elde ettiğiniz özel bir durumdur). Performansların kritik olmadığı ve sistemin makul bir boyutta olduğu ortamlarda bu ekstra iş tamam olabilir. Diğer ortamlarda değildir (gömülü sistemler, cpu performansı için bazen 32/64 bit tamsayı türlerini ve statik bellek yedekleme optimizasyonu için 8/16 bit tamsayı türlerini kullanmak zorunda olduğunuz sistemlerdir).

Geç bağlamayı destekleyen genel amaçlı diller (VB6 gibi çalışma zamanında türlerin çözünürlüğü) bile, geç bağlama kötüye kullanıldığında ortaya çıkan performans isabeti nedeniyle sık sık yazmayı (VB.NET) teşvik etme eğilimindedir ve sık sık türler açık olmadığında çirkin kodla sonuçlanır ( Visual Basic'te Başvuru / Profesyonel Yeniden Düzenleme - Danijel Arsenovski ).


Lütfen "otomatik yazmayı" tanımlayın.

@delnan: ne demek istediğimi geç bağlama ile otomatik yazma yerine :)
Matthieu

Çalışma zamanında türleri çözen çok sayıda genel amaçlı dil var, Common Lisp sadece birini adlandırmak için. (Performans amacıyla, Common Lisp'te türleri bildirebilirsiniz, böylece bunu yalnızca performans açısından kritik bölümlerde yapabilirsiniz.)
David Thornley

@David Thornley: "zorlayıcı" güçlü yazım çok güçlü olabilirdi, "terfi" daha uygun olurdu, cevabımı buna göre güncelledi. Duruma bağlı olarak iki tür bağlayıcı arasında seçim yapmanıza izin veren bir dil, kesinlikle şu ya da bu şekilde zorlanmaktan daha iyidir. Özellikle düşük seviyeli programlama yapmadığınızda ve mantığa odaklandığınızda.
Matthieu

4

Basitlik, Bellek ve Hız Bir değişken bildirdiğimde, o değişkenin belleği bir blokta ayrılır. Dinamik olarak büyüyen bir değişkeni desteklemek için, bu değişkene bitişik olmayan bellek kavramını eklemem gerekir (ya değişkenin temsil edebileceği en büyük bloğu ya da rezerve eder). Bitişik olmayan bellek atama / almadaki performansı düşürür. Mümkün olan en büyük yeri ayırmak, yalnızca bir bayta ihtiyaç duyduğum ancak sistemin uzun süre ayırdığı senaryoda boşa gider.

Bir dizi ve bir vektör (veya bağlantılı liste) arasındaki dengeleri düşünün. Bir dizi ile, belirli bir pozisyon aramak başlangıç ​​pozisyonunu almak ve bellekteki yeni pozisyonu bulmak için bellek işaretçisi x boşluklarını kaydırmak için basit bir konudur. Bir int'i bir bit olarak [32] düşünün, bir int okuması tüm bit değerlerini elde etmek için o dizide yürümeyi içerir.

Dinamik bir sayı türü oluşturmak için, bunu bir bit dizisinden bir bit vektörüne değiştirmeniz gerekir. Dinamik numaranızı okumak, başa gitmeyi, o biti almayı, bir sonraki bitin bellekte nerede olduğunu sormayı, o konuma gitmeyi, o biti almayı vb. İçerir. Dinamik sayıdaki her bit için üç işlem ( geçerli), oku (sonraki adres), taşı (sonraki). Bir milyon sayının değerlerini okuduğunuzu düşünün. Bu bir milyon ekstra operasyon. Önemsiz görünebilir. Ancak her milisaniyenin önemli olduğu sistemleri (finansal gibi) düşünün.

Karar, geliştiricinin boyutu kontrol etmek ve doğrulamak için sistemin performansını etkilemeye kıyasla küçük bir değiş tokuş olduğuna karar verildi.


1
Diğer alternatif, sayı geçerli boyuttan daha büyük olduğunda dizinin yeniden tahsis edildiği dizilişlere benzer sayıları uygulamaktır. Ayrıca, kullanıcının döngü için taşma İSTEMESİ durumunda hesaba katmanız gerekir.
Michael Brown

Bu doğru, ama bir şekilde basitleştirme. Statik olarak yazılan kadar hızlı olmasa da çoğu durumda "yeterince hızlı" olabilirken, daha verimli bir dizi yapısı ortaya çıkarabilirsiniz. örneğin, dizi daha fazla bellek veya performans gerektirmeyecek şekilde tamamen pürüzlü değilse, farklı türdeki bloklara bilgi kaydedebilirsiniz. Ya da dizi, bir tür dizine sahip olmak için bazı belleği feda edebilir. Dizi, içeriğine göre kendini optimize edebilir. Yine de performansa ihtiyaç duyuyorsanız, bellek boyutunu bir tür kısıtlamasıyla yazma seçeneğiniz olabilir.
Homde

Adil olmak gerekirse, ortaya çıkardığınız kadar acımasız değil. Gelecekteki cevabım.
Paul Nathan

3

Donanım merkezli diller ve projeler için belirli türler gereklidir. Kablo ağ protokolleri buna bir örnektir.

Ama - eğlence için - C ++ gibi bir dilde varint türü oluşturalım. Bunu bir new'd ints dizisinden oluşturun.

Ekleme uygulamak zor değildir: sadece baytları birlikte xorve edin ve yüksek bitleri kontrol edin: eğer bir taşıma opererasyonu varsa, newyeni bir üst baytta ve biti taşıyın. Çıkarma, 2'nin tamamlayıcı temsilinde önemsiz bir şekilde izler. (Bu aynı zamanda bir dalgalanma taşıma toplayıcısı olarak da bilinir).

Çarpma da benzer şekilde gerçekleşir; yinelemeli toplama / kaydırma kullanır. Her zaman olduğu gibi, kuyruğunuzdaki gerçek büküm bölüm [*].

Bu olduğunda ne kaybettin?

  • Deterministik zaman. newMutlaka kontrol edilemeyen noktalarda tetiklenebilecek bir syscall ( ) yöntemine sahipsiniz .

  • Deterministik uzay.

  • Yarı yazılım matematiği yavaştır.

Bir donanım katmanlı bir dil kullanarak ve aynı zamanda yüksek (yavaş) seviyesinde çalışan gerekmektedir gerekir ve varsa yok gömmek bir betik motoru istediğiniz bir varintanlamda bir çok yapar. Muhtemelen bir yerde yazılmış.

[*] Bunu yapmanın daha hızlı yolları için Cf donanım matematik algoritmaları - genellikle hile paralel işlemlerdir.


2

Bu iyi bir soru. Python gibi bir dilin neden "kısa, int, uzun, bigint vs." ye ihtiyaç duymadığını açıklar: tamsayılar, tamsayılardır (Python 3'te tek bir tamsayı türü vardır) ve sınır boyutu yoktur ( tabii ki bilgisayarın hafızası).

Unicode'a gelince, UTF-8 kodlaması (Unicode'un bir parçasıdır) ASCII karakterleri için sadece tek bir karakter kullanır, bu yüzden o kadar da kötü değildir.

Daha genel olarak, dinamik diller sizin bahsettiğiniz yöne gidiyor gibi görünmektedir. Bununla birlikte, verimlilik nedenleriyle, bazı durumlarda (daha hızlı çalışması gereken programlar gibi) daha kısıtlı türler yararlıdır. İşlemciler verileri bayt (veya 2, 4, 8 vb. Bayt) olarak düzenlediğinden, öngörülebilir gelecekte çok fazla değişiklik görmüyorum.


1

Dil teorisi temelinde haklısınız. Türler, bir dizi yasal duruma, bu eyaletlerin kullanabileceği dönüşümlere ve bu eyaletlerde gerçekleştirilebilen operasyonlara dayanmalıdır.

Bununla birlikte, tipik haliyle OOP programlamasının size verdiği budur. Aslında, Java'da, nesneyi depolamak için ne kadar gerekli olduğuna göre alan ayıran BigIntegerve BigDecimalsınıflarından etkili bir şekilde bahsediyorsunuz . (FrustratedWithFormsDesigner'ın belirttiği gibi, birçok komut dosyası türü dil bu yolda daha da ileridedir ve bir tür bildirimi bile gerektirmez ve onlara verdiğiniz her şeyi depolar.)

Bununla birlikte, performans hala önemlidir ve çalışma zamanında türleri değiştirmek maliyetli olduğundan ve derleyiciler derleme zamanında bir değişkenin maksimum boyutunu garanti edemediğinden, birçok dilde basit türler için statik boyutlu değişkenlere sahibiz.


Bir çeşit dinamik / uyarlanabilir yazmanın şu an sahip olduğumuzdan daha maliyetli ve daha az performans gösterdiğini ve mevcut derleyicileri kullanmanın kesinlikle olacağını fark ediyorum. Ancak, bir dil ve derleyiciyi sıfırdan oluşturursanız, bunları statik olarak yazılan kadar hızlı değilse, en azından buna değecek kadar hızlı yapamayacağınızdan% 100 emin miyiz?
Homde

1
@MKO: Neden denemiyor ve görmüyorsun?
Anon.

1
Evet, mümkün olduğunca hızlı yapabilirsiniz (ancak muhtemelen sayılar için statik bir sistem kadar hızlı değildir). Ama "buna değer mi" kısmı daha hileli. Çoğu kişi, aralığı bir intveya a'ya rahatça uyan verilerle çalışır doubleve eğer değilse, farkındadırlar, bu nedenle dinamik değer boyutlandırma, ödemeleri gerekmeyen bir özelliktir.
jprete

Elbette tüm programcılar bir gün kendi
dilimi

@jprete: Katılmıyorum; çoğu insan olası büyük ara sonuçların farkında değildir. Böyle bir dil çoğu amaç için yeterince hızlı olabilir ve yapılmıştır.
David Thornley

1

Dile bağlıdır. Python, Ruby, Erlang gibi yüksek seviyeli diller için yalnızca integral ve ondalık sayılar kavramına sahipsiniz.

Bununla birlikte, belirli bir dil sınıfı için bu türlere sahip olmak çok önemlidir. PNG, JPeg gibi ikili biçimleri okumak ve yazmak için kod yazarken, bir kerede ne kadar bilginin okunduğunu tam olarak bilmeniz gerekir. İşletim sistemi çekirdekleri ve aygıt sürücüleri yazma ile aynıdır. Herkes bunu yapmaz ve üst düzey dillerde ayrıntılı ağır kaldırma yapmak için C kütüphanelerini kullanırlar.

İçinde short, daha spesifik türler için hala bir yer var, ancak birçok geliştirme sorunu bu hassasiyeti gerektirmiyor.


0

Son zamanlarda bir merdiven mantığı editörü ve çalışma zamanı oluşturdum ve türlerle çok sınırlı olmaya karar verdim:

  • Boole
  • Numara
  • sicim
  • DateTime

Kullanıcı için daha sezgisel hale getirdiğine inanıyorum. Bu, C gibi bir dilde görebileceğiniz "normal" tipteki tüm PLC'lerden radikal bir kalkıştır.


0

Programlama dilleri bu yönde ilerliyor. Örneğin dizeleri ele alalım. Eski dillerde PIC X(42), COBOL gibi DIM A$(42), BASIC'in bazı sürümlerinde veya SQL'de [ VAR] gibi dizenin boyutunu bildirmeniz gerekir CHAR(42). Modern dillerde, dinamik olarak ayrılmış bir stringtürünüz vardır ve boyutu düşünmenize gerek yoktur.

Ancak tamsayılar farklıdır:

Demek istediğim: gerçekten kısa, int, uzun, bigint vb.'ye ihtiyacımız var mı?

Python'a bir göz atın. Makine boyutlu ( int) ve keyfi boyutlu ( long) tamsayıları ayırt etmek için kullanılır . 3.x'te eski gitti (eski longyenidir int) ve kimse bunu kaçırmaz.

Ama yine de için özel bir tip var dizileri şeklinde 8 bitlik tamsayılar bytesve bytearray. Neden sırasıyla bir tupleveya listtamsayı kullanmıyorsunuz ? Doğru, bytesekstra ip benzeri yöntemlere tuplesahip değil, ancak verimliliğin bununla çok ilgisi vardı.

Şamandıra, gerçek ve çiftler biraz daha zorlayıcıdır, çünkü tip ihtiyacınız olan hassasiyete bağlıdır.

Pek sayılmaz. "Her şey çift kesinliklidir" yaklaşımı çok yaygındır.


1
Belki temel türler, türün temel niyetini, yani "normal" sayılar için int, tüm normal "ondalık sayılar" için iki katına (basitlik için olsa ondalıklara sahip olmamalı mı?) Miktarlar ve baytlarla çalışmak için "para" bildirmelidir ikili verilerle çalışmak için. Bir öznitelik yoluyla bildirilen bir tür kısıtlaması, izin verilen aralık, ondalık kesinlik, geçersizlik ve hatta izin verilen değerleri bildirmeye izin verebilir. Bu şekilde özel ve yeniden kullanılabilir türler oluşturabilirseniz harika olur
Homde

@konrad: IMHO, "imzasız" tamsayıların C'de bu tür baş ağrılarına neden olmalarının nedeni bazen sayıları temsil etmek ve bazen de saran bir soyut cebirsel halkanın üyelerini temsil etmek için kullanılmasıdır. Ayrı "halka" ve "işaretsiz sayı" türlerine sahip olmak unum64 += ring32a-ring32b, varsayılan tamsayı türünün 16 bit veya 64 olmasına bakılmaksızın, like like code'un her zaman doğru davranışı sağlayacağından emin olabilir [kullanımı +=önemlidir; gibi bir ifade unum64a = unum64b + (ring32a-ring32b);belirsiz olarak reddedilmelidir.]
supercat

0

Akıl yürütmeyi, değişkenlerin / nesnelerin hafızada tutulduğunu, hafızanın tahsis edilmesi gerektiğini ve bu nedenle bir değişkenin ne kadar büyük olabileceğini bilmemiz gerektiğini anlıyorum. Ama gerçekten, modern bir programlama dili "uyarlanabilir türleri" işleyemezse, yani bir şey sadece kısa aralıkta tahsis edilirse, daha az bayt kullanır ve bir şey aniden çok büyük bir sayı tahsis edilirse, bellek tahsis edilir belirli bir örnek için.

Şamandıra, gerçek ve çiftler biraz daha zorlayıcıdır, çünkü tip ihtiyacınız olan hassasiyete bağlıdır. Bununla birlikte, dizeler çoğunlukla ascii'nin kullanıldığı birçok durumda (.Net) daha az bellek alabilir; buth dizeleri, unicode kodlaması nedeniyle her zaman belleği iki katına çıkarır.

Fortran'ın benzer bir şeyi vardı (Tam olarak ne demek istediğini bilmiyorum, çünkü gerçekten iki soru görüyorum). Örneğin, F90'da yukarı doğru bir şekilde bir yazı boyutu tanımlamanız gerekmez . Bu iyi, sadece veri türlerinizi tanımlamak için merkezi bir yer sağladığından değil, aynı zamanda bunları tanımlamanın taşınabilir bir yoludur. REAL * 4, tüm işlemcilerdeki (ve işlemci ile CPU + derleyicisi) tüm uygulamalarda aynı değildir, uzun bir görüntü ile değil.

selected_real_kind (p, r) , en az p basamaktan daha büyük ondalık duyarlık ve en az r'den daha büyük üs aralığı ile gerçek bir veri türünün tür değerini döndürür.

Böylece, örneğin;

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

(Bence bu oldukça açıklayıcı bir örnek).

Sorunuzu doğru bir şekilde anlayıp anlamadığımı hâlâ bilmiyorum ve bahsettiğiniz şey bu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.