forked from dlang/dlang.org
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathbuiltin.dd
More file actions
181 lines (140 loc) · 6.58 KB
/
builtin.dd
File metadata and controls
181 lines (140 loc) · 6.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
Ddoc
$(COMMUNITY 言語の機能 vs ライブラリによる実装,
$(P D では、
他の言語(例えばC++)ではライブラリとして実装されているような機能も、
言語そのものの機能として組み込んでいるものがいくつかあります:
)
$(OL
$(LI 動的配列)
$(LI 文字列)
$(LI 連想配列)
)
$(P これを有用な特徴ではなく、
言語の肥大化の証拠と考える方もいらっしゃるようです。
何故、これらそれぞれを標準ライブラリの型として実装しなかったのでしょうか?
)
$(P まず一般的な観点から幾つか理由をあげます:
)
$(OL
$(LI どれも非常によく使われています。従って、例え小さくても、
使い勝手の改善は実現するだけの価値があります。
)
$(LI 言語のコア機能とするということは、その型が不正に使用されていたときに、
コンパイラによって
より適切なエラーメッセージを出すことが可能になります。
ライブラリによる実装では、
実装の内部詳細にもとづいたなんだかよくわからないメッセージになる傾向があります。
)
$(LI ライブラリによる実装では、新しい構文や新しい演算子、
新しいトークンを導入できません。
)
$(LI ライブラリによる実装は、毎回のコンパイルのたびに、
実装の処理でコンパイル時間を消費する傾向にあります。
結果、全体のコンパイル速度が低下します。
)
$(LI ライブラリ実装はエンドユーザに柔軟性を提供するとされています。
しかし、それが標準化されると、
コンパイラ内で標準ライブラリを特別なものとして認識・処理することが許され
(C++標準は実際にこれを認めています)、
言語組み込みの機能と同じ程度の柔軟さになってしまうのです。
)
$(LI 新しいライブラリ型を定義する機能は近年急速な進歩を遂げていますが、
それでもまだ、
既存の言語へのスムーズな統合が望まれる問題点を多く残しています。
荒削りな構造や扱いにくい文法、奇妙な例外事例等々。
)
)
$(P それぞれの項目毎にもっと突っ込んで考えると…:
)
$(SECTION2 動的配列,
$(P C++ は組み込みの配列があります。ですが、あまり使い勝手はよくありません。
これを改善するのではなく、いくつか異なる配列型が C++
標準テンプレートライブラリの中に作られ、
組み込み配列の様々な短所をそれぞれでカバーするようになりました。
そのような拡張配列型には、次のようなものがあります:
)
$(UL
$(LI $(D basic_string))
$(LI $(D vector))
$(LI $(D valarray))
$(LI $(D deque))
$(LI $(D slice_array))
$(LI $(D gslice_array))
$(LI $(D mask_array))
$(LI $(D indirect_array))
)
$(P 組み込みの配列を改善することによって、これら変種の必要性は消えて無くなります。
これら全てをカバーする唯一の配列型があって、
学ぶ必要があるのは一つだけになり、
ある配列を別の種類の配列として使いたい時の問題もなくなります。
)
$(P 通常、型を組み込みとすると、シンタックスシュガーを用意できるようになります。
まず、配列リテラルがありますし、次に配列操作のために用意された演算子があります。
ライブラリによる配列実装だと、
既存の演算子をオーバーロードして使わなければなりません。
添字演算子 $(D a[i])、これはC++と共通です。
さらに、配列結合演算子 $(D ~)、配列追記演算子
$(D ~=)、配列スライス演算子 $(D a[i..j]),
そして配列ベクトル演算演算子
$(D a[]) がDでは加わりました。
)
$(P 結合演算子 ~ と ~= によって、既存の演算子をオーバーロードしなければならないことに
起因する問題が解決されます。通常、ライブラリ実装による結合演算子には
+ が採用されます。
しかしこれは、配列のベクトル加算という + の意味と衝突します。
さらいに、結合はもともと足し算とは関係のない概念で、
両方に同じ演算子を使うのは
混乱の元です。
)
)
$(SECTION2 文字列,
$(REDO $(P <a href="cppstrings.html">C++のstd::stringとの詳細な比較</a> があります。
))
$(P C++ にももちろん、charの配列と文字列リテラルという形で、
組み込みの文字列サポートがあります。問題は単に、
C++の組み込みの配列が貧弱だという点です。
)
$(P でも、文字列が文字の配列でないとしたら、いったい何なのでしょうか。
もし組み込みの配列の問題点が解消されたら、同時に文字列の問題も解決するのでしょうか?
その通り、解決します。最初は D
に文字列クラスがないことを奇妙に感じるかもしれませんが、でも結局、
文字列の操作とは文字の配列の操作に他ならないのです。
もし配列が十分な機能を持っているなら、それ以上のものを加える必要はありません。
)
$(P さらに、文字列リテラルが
ライブラリの文字列クラス型と違う型を持つことによって生じる不自由さも
これで無くなります。
)
)
$(SECTION2 連想配列,
$(P 主な利点は、これも、シンタックスシュガーにあります。
型 $(D T) をキーとして
$(D int) の値を格納する連想配列は、
自然にこう書けます:
)
---------------
int[T] foo;
---------------
$(P 次のような複雑な書き方にはなりません:
)
---------------
import std.associativeArray;
...
std.associativeArray.AA!(T, int) foo;
---------------
$(P 連想配列を言語の機能としてもっておけば、
しばしばリクエストされる機能である
連想配列リテラル を将来的に実装できる可能性があります。
)
)
$(SECTION2 おことわり,
$(P Dは現在のところ複素数型を組み込みで持っていますが、
今後ライブラリ実装へと切り替えられていく予定です。
D言語のセマンティクスとコンパイラ実装の進展によって、
組み込みの複素数型の必要性は薄れました。)
)
)
Macros:
TITLE=言語に機能を組込む理由
WIKI=builtins
CATEGORY_OVERVIEW=$0