特定のタイプはまだ必要ですか?


20

先日私に出くわしたことの1つは、特定のタイプがまだ必要であるか、私たちを阻んでいる遺産です。つまり、short、int、long、bigintなどが本当に必要なのかということです。

私はその理由を理解しています。変数/オブジェクトはメモリに保持され、メモリを割り当てる必要があるため、変数の大きさを知る必要があります。しかし、実際には、現代のプログラミング言語は「適応型」を処理できるはずではありません。つまり、何かがshortintの範囲でしか割り当てられない場合、使用するバイト数が少なくなります。その特定のインスタンスに応じて。

浮動小数点、実数、および倍数は、型が必要な精度に依存するため、少し注意が必要です。ただし、文字列は多くの場合(.Netで)ほとんどメモリを使用することができませんが、Unicodeエンコードのため、文字列は常に2倍のメモリを使用します。

特定の型の引数の1つは、仕様の一部である可能性があります。たとえば、変数が特定の値より大きくなることはないため、shortintに設定します。しかし、代わりに型の制約がないのはなぜですか?変数(およびプロパティ)に許容範囲と値を設定できると、はるかに柔軟で強力になります。

型アーキテクチャは根本的なハードウェアと非常に緊密に統合されており、シリアライゼーションのようなものが実際にトリッキーになる可能性があるため、タイプアーキテクチャを改良する際の大きな問題を認識しています。しかし、プログラミングの観点からすれば、それは素晴らしいはずです?


6
PHP、Ruby、Perlなどでは、変数のタイプを記述する必要はありません。環境はあなたのためにそれを把握します。
FrustratedWithFormsDesigner

7
Unicode文字列は、たまたまASCII(UTF-8)のみに使用される場合、追加のメモリを使用する必要はありません。

2
ただし、バリアント型とアダプティブ型のIMOには違いがあります。バリアントはまったく入力されませんが、割り当てられたときに入力されますが、適応型は入力されますが、より緩やかです。(とI型制約の概念など)
Homde

これは、このプロジェクトを思い出させます。tom.lokhorst.eu
media

4
Adaはどうですか?type hour is range 0 .. 23;
mouviciel

回答:


12

私はこれが事実だと完全に信じています。セマンティック制約は、実装の制約よりも価値があります。何かのサイズを心配することは、オブジェクト指向プログラミングが行われたとき、何かの速度を心配するように感じます。

パフォーマンス重視のプログラミングに取って代わるものではありません。単に、パフォーマンスが重要ではないプログラミングの生産性を高めるだけです。


1
.NET 4.0のコードコントラクトをご覧ください。
スティーブンジュリス

+1データの保存/送信(ネットワークなど)に関しては、プロトコル/実装の効率を最大化するための制約が基本です。また、型付きコレクションが利用可能な場合、多くの根拠が得られます。それ以外は、効率が後部座席を奪う可能性があると想定するのは安全です(特にセマンティックエラーの可能性が減少する場合)。
エヴァンプライス

9

適応を行うための適応型の手段ロジック、そのロジックを実行するための実行時に手段の仕事(テンプレートとコンパイル時には、特定のタイプを必要とする、型推論は、次の2つの世界の最高を得る特殊なケースです)。その余分な作業は、パフォーマンスが重要ではなく、システムが適切なサイズを維持する環境では問題ありません。他の環境ではそうではありません(組み込みシステムはCPUパフォーマンスのために32/64ビット整数型を使用し、静的メモリバックアップ最適化のために8/16ビット整数型を使用する必要がある場合があります)。

遅延バインディング(VB6などの実行時の型の解決)をサポートする汎用言語でさえ、遅延バインディングが悪用されたときに発生するパフォーマンスヒットのために、今では強力な型付け(VB.NET)を促進する傾向があります。型が明示的でないと、いコードになります(リファレンス/ Visual Basicのプロフェッショナルリファクタリング-Danijel Arsenovski)。


「自動入力」を定義してください。

@delnan:自動入力をレイトバインディングに置き換えました。これは私が意図したものです。)
Matthieu

実行時に型を解決する汎用言語がたくさんありますが、Common Lispはただ一つの名前を付けます。(パフォーマンスの目的で、Common Lispで型を宣言できるため、パフォーマンスが重要なセクションでのみ宣言できます。)
デイヴィッドソーンリー

@David Thornley:強い型付けを「強制する」ことは強すぎるかもしれません。「昇格させる」の方が適切だと思います。それに応じて私の答えを更新しました。状況に応じて2種類のバインディングを選択できる言語は、何らかの方法で強制されるよりも確かに優れています。特に、低レベルのプログラミングを行わず、ロジックに焦点を合わせている場合。
マチュー

4

シンプルさ、メモリ、速度 変数を宣言すると、その変数のメモリは1つのブロックに割り当てられます。動的に成長する変数をサポートするには、非連続メモリの概念をその変数に追加する必要があります(変数が表すことのできる最大のブロックを予約するか、その変数を予約します)。連続しないメモリは、割り当て/取得のパフォーマンスを低下させます。必要な最大サイズを割り当てるのは、バイトだけが必要で、システムが長い時間を予約するシナリオでは無駄です。

配列とベクター(またはリンクリスト)のトレードオフを考えてください。配列の場合、特定の位置を探すことは、開始位置を取得し、メモリポインタをxスペースだけシフトして、メモリ内のその新しい位置を見つけるという単純な問題です。intは、ビット[32]がintを読み取ることで、すべてのビット値を取得するためにその配列を調べる必要があると考えてください。

動的な数値型を作成するには、それをビットの配列からビットのベクトルに変更する必要があります。動的な数値の読み取りには、先頭に移動し、そのビットを取得し、次のビットがメモリ内のどこにあるかを尋ね、その場所に移動し、そのビットを取得するなどが含まれます。現在)、読み取り(次のアドレス)、移動(次)。100万個の数値を読むことを想像してください。それは100万の余分な操作です。取るに足らないように見えるかもしれません。しかし、ミリ秒ごとが重要なシステム(財務など)について考えてください。

開発者がサイズを確認して検証する責任を負うことは、システムのパフォーマンスに影響を与えることと比較して小さなトレードオフであるという決定が下されました。


1
もう1つの方法は、配列リストに似た番号を実装することです。この場合、番号が現在のサイズを超えると、配列が再割り当てされます。また、ユーザーがループするオーバーフローを望んでいる場合を考慮する必要があります。
マイケルブラウン

それは本当ですが、いくらか単純化されています。より効率的な配列構造を思い付くことができますが、ほとんどの場合、静的に型付けされるほど速くはないでしょう。たとえば、配列が完全にギザギザでなかった場合、メモリやパフォーマンスをそれほど消費しない場合は、さまざまなタイプのブロックに関する情報を保存できます。または、配列は何らかのメモリを犠牲にして、ある種のインデックスを作成できます。配列は、その内容に基づいて自己最適化することさえできます。パフォーマンスが必要な場合は、型制約を介してメモリサイズを入力するオプションを引き続き使用できます。
オムド

公平を期すために、それはあなたが作るほど残忍ではありません。今後の回答をご覧ください。
ポールネイサン

3

ハードウェア中心の言語およびプロジェクトには、特定のタイプが必要です。1つの例は、有線ネットワークプロトコルです。

しかし、楽しみのために、C ++のような言語のvarint型を作成しましょう。new'd配列のint からビルドします。

加算を実装するのは難しくありません。バイトをまとめて上位ビットをチェックnewするだけです。キャリー操作がある場合は、新しい上位バイトでビットをキャリーします。2の補数表現では、引き算は自明です。(これはリップルキャリー加算器とも呼ばれます)。

乗算も同様に続きます。反復的な加算/シフトを使用します。いつものように、尾の本当のねじれは除算[*]です。

しかし、これが起こると何を失いますか?

  • 確定的な時間。new必ずしも制御可能ではないポイントでトリガーする可能性のあるsyscall()があります。

  • 確定的な空間。

  • 半ソフトウェアの計算は遅いです。

ハードウェアレイヤー言語を使用する必要があり、高(低速)レベルで動作する必要があり、スクリプトエンジンを埋め込みたくない場合はvarint、非常に理にかなっています。おそらくどこかに書かれています。

[*]より高速な方法のためのCfハードウェア数学アルゴリズム-通常、トリックは並列操作です。


2

これはいい質問です。Pythonのような言語が「short、int、long、bigintなど」を必要としない理由を説明します。整数は、まあ、整数(Python 3には単一の整数型があります)であり、制限サイズ(もちろん、コンピューターのメモリ)。

Unicodeに関しては、UTF-8エンコード(Unicodeの一部)はASCII文字に単一の文字のみを使用するため、それほど悪くはありません。

より一般的には、動的言語はあなたが言及した方向に向かうようです。ただし、効率上の理由から、一部のインスタンス(高速で実行する必要があるプログラムなど)では、より制約の多い型が便利です。プロセッサーがバイト(または2、4、8などのバイト)単位でデータを編成するため、近い将来に大きな変化は見られません。


1

言語理論に基づいて、あなたは正しい。タイプは、一連の法的状態、それらの状態で使用可能な変換、およびそれらの状態で実行可能な操作に基づいている必要があります。

ただし、これは、一般的な形式のOOPプログラミングが提供するものです。実際、Javaでは、オブジェクトBigIntegerBigDecimalクラスについて効果的に話します。これらは、オブジェクトの格納に必要な量に基づいてスペースを割り当てます。(FrustratedWithFormsDesignerが指摘したように、多くのスクリプト型言語はこのパスに沿ってさらに進んでおり、型の宣言さえ必要とせず、与えたものは何でも保存します。)

ただし、パフォーマンスは依然として重要です。実行時に型を切り替えるのはコストがかかるため、コンパイラーはコンパイル時に変数の最大サイズを保証できないため、多くの言語の単純な型に対して静的なサイズの変数があります。


ある種の動的/適応型付けは、現在のものよりもコストがかかり、パフォーマンスが低く、現在のコンパイラを使用すると確かにそうなります。しかし、言語とコンパイラを一から構築する場合、静的に型付けされるほど速くなくても、少なくともそれを価値があるほど速く実行することはできません。
Homde

1
@MKO:試してみてはいかがですか?
アノン。

1
はい、実行可能に高速にすることができます(ただし、数値の静的システムほど高速ではありません)。しかし、「それだけの価値はありますか」という部分はもっとトリッキーです。ほとんどの人は、範囲がintaまたはaに快適に収まるデータを操作しますがdouble、そうでない場合は、それを認識しているため、動的な値のサイジングは、支払う必要のない機能です。
jprete

もちろん、すべてのプログラマーとして、いつか自分の言語を作ることを夢見ています;)
Homde

@jprete:私は同意しません。ほとんどの人は、大きな中間結果の可能性に気付いていません。このような言語は、ほとんどの目的に十分な速度で作成できます。
デヴィッドソーンリー

1

言語に依存します。Python、Ruby、Erlangなどの高レベル言語では、整数と10進数の概念しかありません。

ただし、特定のクラスの言語では、これらのタイプを持つことが非常に重要です。PNG、JPegなどのバイナリ形式の読み取りと書き込みを行うコードを作成する場合、一度に読み取られる情報の量を正確に知る必要があります。オペレーティングシステムのカーネルとデバイスドライバーの作成についても同様です。誰もがこれを行うわけではなく、高レベル言語では、Cライブラリを使用して詳細な面倒な作業を行います。

short、そこにはまだ多くの特定のタイプのための場所ですが、多くの開発の問題は、その精度を必要としません。


0

私は最近、ラダーロジックエディターとランタイムを作成しましたが、型を非常に制限することにしました。

  • ブール
  • ひも
  • 日付時刻

ユーザーにとってより直感的になったと思います。これは、Cのような言語で見られるすべての「通常の」範囲のタイプを備えたほとんどのPLCからの根本的な逸脱です。


0

プログラミング言語はその方向に向かっています。文字列を例にとります。古い言語ではPIC X(42)、COBOL、DIM A$(42)BASICの一部のバージョン、またはSQLの[ VAR]のように、文字列のサイズを宣言する必要がありCHAR(42)ます。現代の言語では、動的に割り当てられるstring型は1つだけであり、サイズを考慮する必要はありません。

ただし、整数は異なります。

つまり、short、int、long、bigintなどが本当に必要なのかということです。

Pythonを見てください。マシンサイズ(int)と任意サイズ(long)の整数を区別するために使用されていました。3.xでは、前者はなくなり(古いものlongが新しいint)、誰も見逃しません。

ただし、との形式の8ビット整数のシーケンスには、まだ特殊な型がbytesありbytearrayます。整数tupleまたはlist整数をそれぞれ使用しないのはなぜですか?Trueの場合、bytes追加の文字列のような方法で持っていtupleないが、しかし確実に、効率はそれを行うにはたくさんありました。

浮動小数点、実数、および倍数は、型が必要な精度に依存するため、少し注意が必要です。

あんまり。「すべてが倍精度」アプローチは非常に一般的です。


1
たぶん、基本型は型の基本的な意図を宣言する必要があります。つまり、「通常の」数値の場合はint、すべての通常の「10進数」の場合はdoubleです。バイナリデータを操作するため。属性を介して宣言された型制約により、許可された範囲、10進数の精度、null許容性、さらには許可された値を宣言できます。カスタムで再利用可能な型をそのように作成できたらクールだろう
-Homde

@konrad:私見、「符号なし」整数がCでこのような頭痛の種を引き起こす理由は、それらが数字を表すために時々使われ、時にはラッピング抽象代数リングのメンバーを表すために使われるからです。「リング」型と「符号なし数」型を分離するとunum64 += ring32a-ring32b、デフォルトの整数型が16ビットか64かに関係なく、コードのようなコードが常に正しい動作をすることが保証されます+=。のような表現unum64a = unum64b + (ring32a-ring32b);は曖昧であるとして拒否されるべきです。]
supercat

0

私はその理由を理解しています。変数/オブジェクトはメモリに保持され、メモリを割り当てる必要があるため、変数の大きさを知る必要があります。しかし、実際には、現代のプログラミング言語は「適応型」を処理できるはずではありません。つまり、何かがshortintの範囲でしか割り当てられない場合、使用するバイト数が少なくなります。その特定のインスタンスに応じて。

浮動小数点、実数、および倍数は、型が必要な精度に依存するため、少し注意が必要です。ただし、文字列は多くの場合(.Netで)ほとんどメモリを使用することができませんが、Unicodeエンコードのため、文字列は常に2倍のメモリを使用します。

Fortranにも似たようなものがあります(実際に2つの質問があるので、これが正確にあなたが言っていることかどうかわかりません)。たとえば、F90以降では、明示的に型sizeを定義する必要はありません。これは、データ型を定義する中心的な場所を提供するだけでなく、それらを定義するための移植可能な方法でもあるため、良いことです。REAL * 4は、すべてのプロセッサーのすべての実装で同じではありません(プロセッサーによってはCPUとコンパイラーを意味します)。

selected_real_kind(p、r)は、10進精度が少なくともp桁以上で指数範囲が少なくともrより大きい実データ型のkind値を返します。

たとえば、あなたは行き​​ます。

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

(かなり自明の例だと思います)。

それでもあなたの質問を正しく理解したかどうかはわかりません。これがあなたが言及していることです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.