データ構造を言語に統合する(Pythonなど)か、標準ライブラリに提供する(Javaなど)必要がありますか?


21

Pythonおよび他の多くのプログラミング言語では、共通のデータ構造は、専用の構文を持つコア言語の統合された部分として見つけることができます。LISPの統合リスト構文を別にすれば、配列の上の何らかのデータ構造を構文の統合部分として提供する他のどの言語も考えられません。標準ライブラリでそれらを提供するようです。

言語設計の観点から、コア言語のデータ構造に特定の構文を使用することについてのあなたの意見は何ですか?それは良い考えですか、そして言語の目的(など)は、これがどれほど良い選択であるかを変えますか?

編集:(明らかに)私が意味するデータ構造についての混乱を引き起こしてすみません。基本的で一般的に使用されるものについて説明しますが、それでも最も基本的なものではありません。これには、ツリー(複雑すぎる、珍しい)、スタック(あまり使用されない)、配列(単純すぎる)は含まれませんが、セット、リスト、ハッシュマップなどが含まれます。


1
オブジェクトとハッシュマップを除外していますか?
11

3
@Anto:多くの言語には、連想配列、Perl、PHP、JS(技術的にはここではオブジェクト)などの
形式のハッシュマップが

1
おそらく、配列、リスト、ハッシュマップ/連想配列は別として、どのデータ構造を考えているのかをより具体的にすることができますか?
FrustratedWithFormsDesigner

1
ハッシュマップ、リスト、および「複雑なデータ構造」としてより高度なものを含め、配列を単純すぎるものとして捨てます。
アント

1
もっと理にかなったタイトルは、「言語に含めるべきデータ構造、そしてライブラリに何を含めるべきか」のようなものになると思います。ただし、意味のある答えは言語に大きく依存します。ライブラリを言語にきれいに統合するほど、構造をライブラリに移動することが合理的になります。
ジェリーCo

回答:


13

それは言語が何のためであるかによります。

いくつかの例(他の回答から多少盗まれた):

  • Perlには、ハッシュテーブル、配列、文​​字列用の特別な構文があります。Perlはスクリプトの作成によく使用されますが、これらはスクリプトの作成に役立ちます。
  • Matlabにはリスト、マトリックス、構造のための特別な構文があります。Matlabは、工学のための行列およびベクトル数学を行うためのものです。
  • Java / .NETは文字列と配列をサポートしています。これらは、配列と文字列がよく使用される汎用言語です(新しいコレクションクラスを使用することで、少なくなります)
  • C / C ++は配列をサポートします。これらはあなたからハードウェアを隠さない言語です。文字列は部分的にサポートされています(連結なし、strcpyの使用など)

あなたの言語の目的/精神/聴衆が何であるかによります。ハードウェアからどれほど抽象的で、どの程度離れているか。 一般に、リストをプリミティブとしてサポートする言語では、無限に長いリストを作成できます。C / C ++のような低レベルではこれらは決してありませんが、それはこれらの言語の精神である目標ではないためです。

私にとって、ガベージコレクションは同じロジックに従っています。言語の視聴者は、メモリがいつ割り当てられるか、解放されるかを正確に知ることに関心がありますか?はいの場合、malloc / free; いいえの場合、ガベージコレクション。


6
これは、「C / C ++」という用語を使用するのに悪い場所です。C++での高レベルのテンプレートタイプの存在は、2つの言語の大きな違いだからです。
dan04

ガベージコレクションは確定的な方法で行うことができます。必要なのは線形型(またはそれらの貧乏人の代替:RAII)だけです。
ピョン

EduardoLeón@あなたは、確定時点でガベージコレクションを呼び出すことができますが、私はそれがために実行されますどのくらいとは思わない決定論的である(同じ理由でそれmallocnewC / C ++で非決定的です)。
earlNameless

@earlNameless:リソースの使用状況に応じて決定論的です:線形型(または類似の一意性型)は、型エラー(したがって、コンパイルエラー)になり、リソースを解放しません(型によってキャプチャされない可能性を調整します)システム、プログラムの異常終了)、またはそれらが破棄された後にそれらを使用する。
ピョン

5

Perlにはハッシュマップがあり、PL / SQLはレコードをサポートしており、さまざまな次元のベクトルと行列をサポートする構文を持つmatlabの非常に霧の深い思い出があります(これについては間違っている可能性があり、これらはデータではなくデータ型であると主張することができます構造)...非常に一般的な構造をネイティブにサポートするのは良いことだと思います。通常、配列とハッシュマップ/連想配列は、最も一般的にネイティブにサポートされている構造であり、おそらく最も一般的に使用されているようです。

バイナリツリーなどの他の構造のネイティブ構文サポートを追加する場合、それらの構造も言語のサポートツール(コンパイラ/ランタイム/など)によって実装されていることを忘れないでください。いくつの構造をサポートしたいですか?

あまり一般的にサポートされていない構造に対して、新しい表記法を考案する必要があります... Keep It Simple!。


たとえば、ツリーのリテラル構文を作成する必要はありません。これらはまれであり、多くの言語のstdlibにもありません。同じ議論で、「あまり一般的ではない操作のための新しい表記法を考案しなければならない」ため、演算子を含めることに反対することもできます。

@delnan:新しい言語を設計し、配列以外のデータ構造を(おそらく)新しい構文でネイティブにサポートする必要があるかどうか、またはライブラリを含めることでサポートする必要があるかどうかという観点から理解しました。
FrustratedWithFormsDesigner

さて、最初の文は「共通のデータ構造」について明示的に述べているので、OPはこれまでに発明されたすべての不明瞭なデータ構造に特別な構文を追加しようとするのに十分ではありません

@delnan:...そして、OPはLISPリストと配列を除外します(一般的に) "... LISPの統合リスト構文は別として、私が知っている他の言語は考えられません。データ構造配列上でその構文の統合された部分として、」...私は、彼らが配列/リストよりも多くのエキゾチックなデータ構造を熟考と思っていたので...
FrustratedWithFormsDesigner

はい(「配列の上」を「他の一般的なデータ構造」と解釈しました)が、質問の中には「所有しているすべてのデータ構造のリテラルを作成しましょう」というヒントはありません。これが合理的なものに限定されるべきであると述べることは問題ありませんが、この仮定のためだけに「悪い考え」と言うことはできないと思います。

5

ここで私のお気に入りの例はLuaです。Luaには「テーブル」というデータタイプが1つだけありますが、その柔軟性と速度は、通常の配列、リンクリスト、キュー、マップの代わりに実際に使用することを意味し、Luaのオブジェクト指向機能の基礎にもなります(つまり、クラス)。

Luaは驚くほど単純な言語ですが、テーブルデータ構造の柔軟性により、Luaも非常に強力です。


2
JavaScriptオブジェクトは実際には同じ方法です。たとえば、配列は単なる数値プロパティと長さを持つオブジェクトです。
ティコンジャービス

1
LuaテーブルはJavaScriptオブジェクトとは異なります。JavaScriptではJavaScript {}ではなく[]、Lua {}では両方に使用できます。Luaの表は、Lispのリストと比べて優れています。
ヤコブ

JavaScriptでは、「すべてがオブジェクトである」(配列を含む)と思いますが、すべてが配列ではありません。Luaでは、すべてがテーブルです。
ディーンハーディング

3

高度なデータ型ごとに専用の構文を用意する必要はありません。たとえば、のset([1, 2, 3])代わりに(Python 2.xのように)持つことは許容でき{1, 2, 3}ます。

重要なのは持っているいくつかのハイレベルなデータ構造を構築するための便利な方法を。避けたいのは次のようなコードです:

s = set()
s.add(1)
s.add(2)
s.add(3)

C ++ で、、を使用するstd::vectorstd::set、非常に悩まさstd::mapれます。ありがたいことに、新しい標準にはがありstd::initializer_listます。


3

私の意見では、それは驚くほど単純な追加であり、少なくとも注意を払って-よく知られているリテラルを持つタプル、リスト、マップ、およびセットの場合は少なくとも、驚くほど頻繁に便利です。

  • 言語に追加するのは安価です。貴重な複雑さの予算はそれほどかかりません。
    • 文法は基本的にsomeBracket {expr ','} someBracketまたはsomeBracket {expr ':' expr ','} someBracketです。オプションの末尾のカンマのようなものが必要な場合は、いくつかの単純な余分なものがあります。フロートリテラルは簡単な文法で長くすることができます。
    • 多くの言語では、人気のあるリテラルはいずれも既存の構文と競合しません(私が考えることができる例外は、式としてのブレースのようなブロック、カンマ演算子、セミコロンなしの言語です{1, 2}
    • セマンティクスが5つ未満の文で定義することができ、非公式のバージョンが「インスタンス化新しい$コレクション、その後、呼び出し.add/ .append/ .setItemその(それらの)表現(s)は、引数として与えられたとの表現に一回」。
  • 前の3番目の点により、実装も非常に簡単です。
  • 必要なときに非常に便利で、他の要素の構文に影響を与える(必要とする)ことはありません。つまり、使用しないときに「支払う」必要はありません。

3

Clojureはlispですが、サポートしています

Lists: (x1 x2)
Vectors: [x1 x2]
Maps: {k1 v1 k2 v2}
Sets: #{x1 x2}

2

言語自体のデータ構造が多いほど、言語の学習は難しくなります。それは個人的な好みかもしれませんが、私はよりシンプルな言語を好む傾向があり、その後、ライブラリから追加を提供できます。

特定のフィールド用に設計された言語は、Matlabなどの言語に特定のデータ構造が組み込まれていることで恩恵を受ける場合があります。しかし、多すぎるとあなたを圧倒できます。


2

言語が本当に役立つためには、一定のタスクをすぐに実行する必要があります。実用的な日々のプログラミングには、一般的なレベルで問題を解決するツールが必要だからです。ミニマリズムはコンパクトでクールに見えますが、繰り返し使用される大きな問題を解決するために使い始めるには、その上に構築できるレベルの抽象化が必要です。

そのため、プログラミング言語は、その言語が設計されているタスクの構文で最も一般的に使用されるデータ構造のサポートを提供すべきだと思います。


2

一般に、リストやセットなどのリテラルを持っていると便利です。しかし、PythonリストやJavascript配列の実際の実装(たとえば)について何も知らないということが時々私を悩ませます。私が確信できる唯一のことは、それらが与えられたインターフェースを公開することです。

言語表現力のベンチマークとして、独自のデータ構造をライブラリとしてどれだけうまく記述でき、それらを使用するのがどれほど便利かを考えています。

たとえば、Scalaはさまざまな実装とパフォーマンスの保証を備えたさまざまなコレクションを提供します。それらはすべてScala自体に実装されており、それらを使用する構文は、組み込みで実行時サポートがある場合よりも少しだけ複雑です。

少なくともマネージ言語では、ランタイム自体からのサポートが実際に必要な唯一の基本構造は配列です。メモリを管理しないと、大量の隣接バイトを取得するのが難しくなります。他のすべての構造は、配列とポインター(または参照)から構築できます。


1

APL(および関連する最新のバリアント、A +、J、およびK)は、スカラー、ベクトル、およびマトリックスをファーストクラスのデータ構造として持っています。

はい、それらは配列の単なるバリアントとして非推奨にできます。しかし、それらは複雑な宣言からも解放されており、別個のライブラリーからもたらされるのではなく、言語の第一級の部分である複雑なデータ構造のように感じます。


APLにはネストされた配列もあり、配列は同種のデータ型である必要はありません。すべてが非常に強力なデータ構造になります。
RFlack 2014年

1

言語設計の観点から、コア言語のデータ構造に特定の構文を使用することについてのあなたの意見は何ですか?それは良い考えですか、そして言語の目的(など)は、これがどれほど良い選択であるかを変えますか?

リストおよびマップのリテラルと便利なクロージャー構文は、高水準言語の重要な機能です。

このJavaコードの違い:

Thing t = new Thing();
t.setFoo(3);
t.setBar(6.3);
t.setBaz(true);

このGroovyコード:

t = new Thing(foo: 3, bar: 6.3, baz: true)

巨大です。40,000行のプログラムと10,000行のプログラムの違いです。構文が重要です。


C#では次のことができます。- var t = new Thing(foo: 3, bar: 6.3, baz: true);あと4文字のみ。
ジョブ

実際には同じ番号です。Groovyコードは「def t = ...」と読みます
kevin cline

1

確かにプログラミング言語のアプリケーションに依存しますが、より高いレベルの言語では、一般的なデータ構造を扱うことができる限り便利である必要があります。見てい抽象データ型のリスト例についてはウィキペディアでは。次の基本原則が最も一般的であることがわかりました(ただし、他の意見も聞きたいです)。

  • 順序付けられたシーケンス(1次元):配列、キュー、スタック、リスト...
  • 順序付けられた多次元構造:テーブル、ベクトル、マトリックス
  • マップ:ハッシュマップ、辞書、セット、マルチマップ...(1次元)
  • 多次元マップ:関数、マップのマップ...
  • グラフの種類:木、有向グラフ...

任意の構造を他の構造でエミュレートできます-それは、プログラミング言語がどの程度簡単かつ明確に許可しているかによって決まります。例えば:

  • キューとスタックは配列またはリストで簡単にエミュレートでき、後者はプッシュ、ポップ、シフトなどの操作を提供します。
  • 順序付けられたシーケンスは、数値キーを持つマップでエミュレートできます
  • セットは、値をブール値にマップするマップによってエミュレートできます
  • ほとんどのグラフタイプは、シーケンスまたはマップをネストすることでエミュレートできます
  • 定義を簡単に変更できる場合は、関数を使用してマップをエミュレートできます

ほとんどの言語では、順序付きシーケンス、1次元マップ用、および多次元マップ用の少なくとも1つのタイプが機能に限定されています。個人的には、Perl、PHP、JavaScript、Luaなどの言語の多次元構造のセットや順序付けを見逃すことがよくあります。それらをエミュレートするだけでは十分ではないからです。


1

特別な構文を取得する特権データ型が多すぎるのは悪い考えだと思います。これにより、言語の構文が不必要に複雑になり、コードが読みにくくなり、初心者が学習しにくくなり、言語のツールを開発するのが難しくなります。

少数の非常に一般的なデータ構造タイプに対して例外を作成しても構いません。おそらく最大で許可します:

  • 固定長配列
  • セット
  • ハッシュマップ
  • シーケンス/リスト
  • レコード/構造体/クラス

それよりも高度なものは、おそらくカスタムデータ型の言語の通常の構文を使用して、処理するライブラリに任せる必要があります。

特に、Red / Blackツリー、Priority Queueなどには実装オプションが非常にたくさんあるため、特定の実装をコア言語にベイクすることは賢明ではありません。人々が自分の状況に最も適切な実装を選択できるようにした方が良いです。言語設計者に私の選択を制限したくないかもしれない実装選択の例:

  • 可変または不変?
  • nullを許可するかどうか
  • 同期するかどうか
  • 永続的なストレージに支えられているかどうか
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.