OSDN Git Service

42fd705d09dab98ac2ea6a3d805812690640aa85
[omake-japanese/omake_trans.git] / src / language-examples.rst
1 .. 7-language-examples
2
3 .. index::
4    single: osh
5 .. _label7:
6
7 7. さらなる言語例
8 =======================================
9 .. In this section, we'll explore the core language through a series of examples (examples of the build system are the topic of the Chapter 3).
10
11 この章では、一連の例を通して言語の核心へと迫ります(ビルドシステムのサンプルについては :ref:`label3` を参照してください)。
12
13 .. For most of these examples, we'll use the osh command interpreter. For simplicity, the values printed by osh have been abbreviated.
14
15 私たちはこれらの例のほとんどに ``osh`` インタープリターを用いています。また、簡単にするため、 ``osh`` によって出力された値は省略されています。
16
17 .. _label7.1:
18
19 7.1 文字列と配列
20 ---------------------------------------
21 .. The basic OMake values are strings, sequences, and arrays of values. Sequences are like arrays of values separated by whitespace; the sequences are split on demand by functions that expect arrays.
22
23 OMakeの基本となる型は文字列とシーケンス、そして値からなる配列です。シーケンスはホワイトスペースによって分割された配列のようなもので、関数の要求に応じて分割されます。 ::
24
25    osh> X = 1 2
26    - : "1 2" : Sequence
27    osh> addsuffix(.c, $X)
28    - : <array 1.c 2.c> : Array
29
30 .. Sometimes you want to define an array explicitly. For this, use the [] brackets after the variable name, and list each array entry on a single indented line.
31
32 時々あなたは明示的に配列を定義したいと思うでしょう。この場合、 ``[]`` を変数名の後に追加し、配列の成分をそれぞれインデントされた行に書くことで実現できます。 ::
33
34    osh> A[] =
35            Hello world
36            $(getenv HOME)
37    - : <array "Hello world" "/home/jyh"> : Array
38
39 .. One central property of arrays is that whitespace in the elements is significant. This can be useful, especially for filenames that contain whitespace. 
40
41 配列は成分にホワイトスペースを含めることができます。これは配列の主要な特徴の一つであり、重要な役割を担います。また、これはホワイトスペースを含むファイル名にとって特に役立ちます。 ::
42
43    # ディレクトリ中の現在のファイルを並べる
44     osh> ls -Q
45     "fee"  "fi"  "foo"  "fum"
46     osh> NAME[] = 
47             Hello world
48     - : <array "Hello world"> : Array
49     osh> touch $(NAME)
50     osh> ls -Q
51     "fee"  "fi"  "foo"  "fum"  "Hello world"
52
53 .. _label7.2:
54
55 7.2 クオート文字列
56 ---------------------------------------
57 .. A String is a single value; whitespace is significant in a string. Strings are introduced with quotes. There are four kinds of quoted elements; the kind is determined by the opening quote. The symbols ' (single-quote) and " (double-quote) introduce the normal shell-style quoted elements. The quotation symbols are included in the result string. Variables are always expanded within a quote of this kind. Note that the osh(1) (Chapter 15) printer escapes double-quotes within the string; these are only for printing, they are not part of the string itself.
58
59 ``String`` は単一の値です。文字列の中でホワイトスペースは重要な意味を持っています。文字列をクオートするには4通りの方法があります。まず一番目にクオートをつけることが挙げられるでしょう。シンボル ``'`` (シングルクオート)と ``"`` (ダブルクオート)を用いることで、シェルを扱うときのように成分をクオートすることができます。クオーテーションシンボルは結果の文字列に **含まれます** 。変数は常に内部にクオートを含んだ状態で展開されます。 ``osh(1)`` (15章で説明)は文字列にダブルクオートをつけて出力しますが、これは出力時だけであり、文字列の中には含まれていないことに注意してください。 ::
60
61     osh> A = 'Hello "world"'
62     - : "'Hello \"world\"'" : String
63     osh> B = "$(A)"
64     - : "\"'Hello \"world\"'\"" : String
65     osh> C = 'Hello \'world\''
66     - : "'Hello 'world''" : String
67
68 .. A second kind of quote is introduced with the $' and $" quotes. The number of opening and closing quote symbols is arbitrary. These quotations have several properties: 
69       * The quote delimiters are not part of the string.
70       * Backslash \ symbols within the string are treated as normal characters.
71       * The strings may span several lines.
72       * Variables are expanded within $" sequences, but not within $' sequences. 
73
74 二番目の方法は ``$'`` と ``$"`` クオートを導入することです。始まりと終わりのクオートシンボルの数は任意です。また、これらのクオーテーションはいくつかの性質をもっています。
75
76 * クオートデリミタは文字列の一部では **ありません** 。
77 * 文字列中のバックスラッシュ ``\`` 文字は通常の文字として扱われます。
78 * 文字列は何行にわたって書くこともできます。
79 * 変数は ``$"`` を用いて展開することができます。ただし、 ``$'`` では展開できません。
80
81 ::
82
83     osh> A = $'''Here $(IS) an '''' \(example\) string['''
84     - : "Here $(IS) an '''' \\(example\\) string[" : String
85     osh> B = $""""A is "$(A)" """"
86     - : "A is \"Here $(IS) an '''' \\(example\\) string[\" " : String
87     osh> value $(A.length)
88     - : 38 : Int
89     osh> value $(A.nth 5)
90     - : "$" : String
91     osh> value $(A.rev)
92     - : "[gnirts )\\elpmaxe(\\ '''' na )SI($ ereH" : String
93
94 .. Strings and sequences both have the property that they can be merged with adjacent non-whitespace text.
95
96 文字列とシーケンスの両方はホワイトスペースが含まれていない文字列とくっつけることができます。 ::
97
98     osh> A = a b c
99     - : "a b c" : Sequence
100     osh> B = $(A).c
101     - : <sequence "a b c" : Sequence ".c" : Sequence> : Sequence
102     osh> value $(nth 2, $(B))
103     - : "c.c" : String
104     osh> value $(length $(B))
105     - : 3 : Int
106
107 .. Arrays are different. The elements of an array are never merged with adjacent text of any kind. Arrays are defined by adding square brackets [] after a variable name and defining the elements with an indented body. The elements may include whitespace.
108
109 配列は異なります。配列の成分はどのような方法を用いても文字列とくっつけることができません。配列は括弧 ``[]`` を変数名につけ、インデントした内容を記述することで成分を定義できます。各成分にはホワイトスペースを含めることもできます。 ::
110
111     osh> A[] =
112             a b
113             foo bar
114     - : <array
115            "a b" : Sequence
116            "foo bar" : Sequence>
117            : Array
118     osh> echo $(A).c
119     a b foo bar .c
120     osh> value $(A.length)
121     - : 2 : Int
122     osh> value $(A.nth 1)
123     - : "foo bar" : Sequence
124
125 .. Arrays are quite helpful on systems where filenames often contain whitespace.
126
127 配列はしばしばシステム上にホワイトスペースを含んだファイル名を使う場合において、非常に有用なツールとなります。 ::
128
129     osh> FILES[] =
130              c:\Documents and Settings\jyh\one file
131              c:\Program Files\omake\second file
132
133     osh> CFILES = $(addsuffix .c, $(FILES))
134     osh> echo $(CFILES)
135     c:\Documents and Settings\jyh\one file.c c:\Program Files\omake\second file.c
136
137 .. _label7.3:
138
139 7.3 ファイルとディレクトリ
140 ---------------------------------------
141 .. OMake projects usually span multiple directories, and different parts of the project execute commands in different directories. There is a need to define a location-independent name for a file or directory.
142
143 複数のディレクトリにまたがっており、かつ異なったパートに分かれているOMakeのプロジェクト上では、まったく違うディレクトリ上でコマンドが実行されます。これはファイル、あるいはディレクトリの名前が位置的に独立して定義されている必要があることを表しています。
144
145 .. This is done with the $(file <names>) and $(dir <names>) functions.
146
147 この問題は ``$(file <names>)`` や ``$(dir <names>)`` 関数を用いて解決できます。 ::
148
149    osh> mkdir tmp
150    osh> F = $(file fee)
151    osh> section:
152             cd tmp
153             echo $F
154    ../fee
155    osh> echo $F
156    fee
157
158 .. Note the use of a section: to limit the scope of the cd command. The section temporarily changes to the tmp directory where the name of the file is ../fee. Once the section completes, we are still in the current directory, where the name of the file is fee.
159
160 ``section:`` を用いて ``cd`` コマンドのスコープに制限を加えていることに注意してください。このセクションでは一時的に ``tmp`` ディレクトリに移動しているので、ファイルの名前には ``../fee`` が用いられます。このセクションが終了してカレントディレクトリに戻ってきたとき、ファイルの名前には ``fee`` が用いられます。
161
162 .. One common way to use the file functions is to define proper file names in your project OMakefile, so that references within the various parts of the project will refer to the same file.
163
164 ファイル関数を使う主な目的は、あなたのプロジェクトの ``OMakefile`` で、ファイル名が正しく定義されるようにするためです。これを用いればプロジェクト上の様々なパートに移動したとしても、変数は同一のファイルを指し示します。 ::
165
166     osh> cat OMakefile
167     ROOT = $(dir .)
168     TMP  = $(dir tmp)
169     BIN  = $(dir bin)
170     ...
171
172 .. note::
173    訳注: file, dirについて詳しく知りたい方は ":ref:`label10.1.1`" を参照してください。
174
175 .. index::
176    single: mapprefix()
177    single: addprefix()
178    single: addsuffix()
179    single: mapsuffix()
180    single: foreach()
181 .. _label7.4:
182
183 7.4 イテレーション、マップ、foreach
184 ---------------------------------------
185 .. Most builtin functions operate transparently on arrays.
186
187 ほとんどのビルドイン関数では配列を何も考慮することなく処理できます。 ::
188
189     osh> addprefix(-D, DEBUG WIN32)
190     - : -DDEBUG -DWIN32 : Array
191     osh> mapprefix(-I, /etc /tmp)
192     - : -I /etc -I /tmp : Array
193     osh> uppercase(fee fi foo fum)
194     - : FEE FI FOO FUM : Array
195
196 .. The mapprefix and addprefix functions are slightly different (the addsuffix and mapsuffix functions are similar). The addprefix adds the prefex to each array element. The mapprefix doubles the length of the array, adding the prefix as a new array element before each of the original elements.
197
198 ``mapprefix`` と ``addprefix`` 関数は全く異なります( ``addsuffix`` と ``mapsuffix`` 関数も同様です)。 ``addprefix`` 関数は接頭辞を各々の成分にくっつけます。 ``mapprefix`` 関数は元の成分の前に新しい接頭辞を成分として加えるので、配列の長さは2倍になります。
199
200 .. Even though most functions work on arrays, there are times when you will want to do it yourself. The foreach function is the way to go. The foreach function has two forms, but the form with a body is most useful. In this form, the function takes two arguments and a body. The second argument is an array, and the first is a variable. The body is evaluated once for each element of the array, where the variable is bound to the element. Let's define a function to add 1 to each element of an array of numbers.
201
202 ほとんどの関数は配列でも動きますが、あなた自身が配列にも対応した関数を作りたいと思うこともあるでしょう。 ``foreach`` 関数はその要望を実現します。 ``foreach`` 関数は二つの表記を使いますが、このコードを伴った表記法はとても便利です。この関数は二つの引数とコードが必要です。まず、一つ目の引数は変数で、二つ目のは配列を指定します。そして ``foreach`` のコードは各々の成分を対象に、引数で指定された変数がその成分に束縛された状態で、配列の長さぶんだけ実行されます。さあ、それでは値を持った配列の各々の成分に1を加える関数を定義してみましょう。 ::
203
204    osh> add1(l) =
205             foreach(i, $l):
206                 add($i, 1)
207    osh> add1(7 21 75)
208    - : 8 22 76 : Array
209
210 .. Sometimes you have an array of filenames, and you want to define a rule for each of them. Rules are not special, you can define them anywhere a statement is expected. Say we want to write a function that describes how to process each file, placing the result in the tmp/ directory.
211
212 あなたはファイル名を持った配列を持ち、そのそれぞれにビルドルールを定義したいと思うこともあるでしょう。ビルドルールは特別なものではなく、あなたはどの箇所でもビルドルールを定義することができます。さて、私たちは配列にある、各々のファイルの処理について記述し、さらに結果を ``tmp/`` ディレクトリの中に置く関数を書きたいものとします。 ::
213
214    TMP = $(dir tmp)
215
216    my-special-rule(files) =
217       foreach(name, $(files))
218          $(TMP)/$(name): $(name)
219             process $< > $@
220
221 .. Later, in some other part of the project, we may decide that we want to use this function to process some files.
222
223 後に、プロジェクトの他の部分で、私たちはこの関数を用いていくつかのファイルを処理することを決めたとしましょう。 ::
224
225    # src/libに処理するためのファイルが入っています
226    MY_SPECIAL_FILES[] =
227        fee.src
228        fi.src
229        file with spaces in its name.src
230    my-special-rule($(MY_SPECIAL_FILES))
231
232 .. The result of calling my-special-rule is exactly the same as if we had written the following three rules explicitly.
233
234 ``my-special-rule`` を呼んだ結果は、以下の3つのルールを明示的に書いた場合と全く同じになります。 ::
235
236     $(TMP)/fee.src: fee.src
237         process fee > $@
238     $(TMP)/fi.src: fi.src
239         process fi.src > $@
240     $(TMP)/$"file with spaces in its name.src": $"file with spaces in its name.src"
241         process $< > $@
242
243 .. Of course, writing these rules is not nearly as pleasant as calling the function. The usual properties of function abstraction give us the usual benefits. The code is less redundant, and there is a single location (the my-special-rule function) that defines the build rule. Later, if we want to modify/update the rule, we need do so in only one location.
244
245 もちろん、これらのルールを記述することは関数を呼ぶことより好ましいものではありません。関数を抽象化することによる普通の特性は、普通の利点となります。ビルドルールを定義するためのコードが一つだけで済み、コードはさらに短くなります。後でもし私たちがルールを修正したりアップデートしたいと思ったときも、単純に一つのルールを修正するだけでよいのです。
246
247 .. index::
248    single: 遅延評価変数
249 .. _label7.5:
250
251 7.5 遅延評価式
252 ---------------------------------------
253 .. Evaluation in omake is normally eager. That is, expressions are evaluated as soon as they are encountered by the evaluator. One effect of this is that the right-hand-side of a variable definition is expanded when the variable is defined.
254
255 omakeでの評価は通常の場合先行して行われます。これは、omakeが式に遭遇した場合、即座に評価が行われることを意味しています。この効果の一つとして、変数定義式の右側は、変数が定義される時点で展開されることが挙げられます。
256
257 .. There are two ways to control this behavior. The $`(v) form introduces lazy behavior, and the $,(v) form restores eager behavior. Consider the following sequence.
258
259 この振る舞いをコントロールするための2つの方法があります。 ``$`(v)`` は遅延評価を行うための、 ``$,(v)`` は先行評価に戻すための表記法です。以下のシーケンスについて考えてみましょう。 ::
260
261     osh> A = 1
262     - : "1" : Sequence
263     osh> B = 2
264     - : "2" : Sequence
265     osh> C = $`(add $(A), $,(B))
266     - : $(apply add $(apply A) "2" : Sequence)
267     osh> println(C = $(C))
268     C = 3
269     osh> A = 5
270     - : "5" : Sequence
271     osh> B = 6
272     - : "6" : Sequence
273     osh> println(C = $(C))
274     C = 7
275
276 .. The definition C = $`(add $(A), $,(B)) defines a lazy application. The add function is not applied in this case until its value is needed. Within this expression, the value $,(B) specifies that B is to be evaluated immediately, even though it is defined in a lazy expression.
277
278 ``C = $`(add $(A), $,(B))`` では遅延評価を定義しています。 ``add`` 関数はこの場合、実際に値が必要となるときまで評価しません。上の式を見てみると、 ``$,(B)`` は ``B`` が即座に評価する変数であることを指定します。これが遅延評価式の中で定義されているにもかかわらずです。
279
280 .. The first time that we print the value of C, it evaluates to 3 since A is 1 and B is 2. The second time we evaluate C, it evaluates to 7 because A has been redefined to 5. The second definition of B has no effect, since it was evaluated at definition time.
281
282 最初私たちが ``C`` の値を出力したとき、 ``A`` は1で ``B`` が2であったので、結果は3と評価されました。次に私たちが同様に ``C`` を出力したとき、 ``A`` は5に再定義されていたので、結果は7と評価されました。二回目の ``B`` は ``C`` の定義時に評価されているため、なんの影響も与えていません。
283
284 .. _label7.5.1:
285
286 7.5.1 遅延評価式についての追加例
287 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
288 .. Lazy expressions are not evaluated until their result is needed. Some people, including this author, frown on overuse of lazy expressions, mainly because it is difficult to know when evaluation actually happens. However, there are cases where they pay off.
289
290 遅延評価式は実際に結果が必要とされるときまで評価されません。筆者を含む結構な人数のプログラマは、遅延評価を多用しているコードを見ると眉をひそめます。なぜならこれは実際にどこで評価が行われているのか分かりにくくなるからです。しかしながら、これらの難点をペイオフできるケースも確かに存在します。
291
292 .. One example comes from option processing. Consider the specification of “include” directories on the command line for a C compiler. If we want to include files from /home/jyh/include and ../foo, we specify it on the command line with the options -I/home/jyh/include -I../foo.
293
294 一つの例としてオプションの処理が挙げられます。Cコンパイラに"include"ディレクトリの指定をコマンドライン上から指定する場合を考えましょう。もし私たちが"/home/jyh/include"と"../foo"上のファイルをインクルードしたい場合、コマンドラインにはオプション ``-I/home/jyh/include -I../foo`` を指定する必要があります。
295
296 .. Suppose we want to define a generic rule for building C files. We could define a INCLUDES array to specify the directories to be included, and then define a generic implicit rule in our root OMakefile.
297
298 Cファイルをビルドするための通常のルールを定義する場合について考えましょう。私たちはインクルードされるディレクトリを指定するため、 ``INCLUDES`` 配列を定義し、ルートの ``OMakefile`` に通常用いる暗黙のルールを定義しました。 ::
299
300     # Cファイルをコンパイルする通常の設定
301     CFLAGS = -g
302     INCLUDES[] =
303     %.o: %.c
304        $(CC) $(CFLAGS) $(INCLUDES) -c $<
305
306     # srcディレクトリは4つのソースファイルからmy_widgetをビルドします。
307     # これはインクルードディレクトリからインクルードファイルを読み込みます。
308     .SUBDIRS: src
309         FILES = fee fi foo fum
310         OFILES = $(addsuffix .o, $(FILES))
311         INCLUDES[] += -I../include
312         my_widget: $(OFILES)
313            $(CC) $(CFLAGS) -o $@ $(OFILES)
314
315 .. But this is not quite right. The problem is that INCLUDES is an array of options, not directories. If we later wanted to recover the directories, we would have to strip the leading -I prefix, which is a hassle. Furthermore, we aren't using proper names for the directories. The solution here is to use a lazy expression. We'll define INCLUDES as a directory array, and a new variable PREFIXED_INCLUDES that adds the -I prefix. The PREFIXED_INCLUDES is computed lazily, ensuring that the value uses the most recent value of the INCLUDES variable.
316
317 しかしこれは全く正しいというわけではありません。問題としては、 ``INCLUDES`` はオプションが格納されてある配列であり、ディレクトリではないという点です。もし私たちが後にディレクトリ名を変更したい場合は、まず ``-I`` 接頭辞を配列から分割する必要があり、これは混乱の元となります。さらに、私たちはディレクトリの絶対パスを使用していません。この問題を解決する方法は、遅延評価式を使うことです。まず私たちは ``INCLUDES`` をディレクトリの配列として定義し、さらに新しい変数 ``PREFIXED_INCLUDES`` を定義することによって ``-I`` 接頭辞を追加します。 ``PREFIXED_INCLUDES`` は遅延評価を行うことで、最新の ``INCLUDES`` 変数値が使われることを保証してくれます。 ::
318
319     # Cファイルをコンパイルする通常の設定
320     CFLAGS = -g
321     INCLUDES[] =
322     PREFIXED_INCLUDES[] = $`(addprefix -I, $(INCLUDES))
323     %.o: %.c
324        $(CC) $(CFLAGS) $(PREFIXED_INCLUDES) -c $<
325
326     # 今回の例では、私たちはインクルードディレクトリの絶対パスを定義しました。
327     STDINCLUDE = $(dir include)
328
329     # srcディレクトリは4つのソースファイルからmy_widgetをビルドします。
330     # これはインクルードディレクトリからインクルードファイルを読み込みます。
331     .SUBDIRS: src
332         FILES = fee fi foo fum
333         OFILES = $(addsuffix .o, $(FILES))
334         INCLUDES[] += $(STDINCLUDE)
335         my_widget: $(OFILES)
336            $(CC) $(CFLAGS) -o $@ $(OFILES)
337
338 .. Note that there is a close connection between lazy values and functions. In the example above, we could equivalently define PREFIXED_INCLUDES as a function with zero arguments.
339
340 遅延する値と関数が密接に繋がっていることに注目してください。上の例では、私たちは ``PREFIXED_INCLUDES`` を、引数を持たない関数として定義しているのと同じことを行っています。 ::
341
342     PREFIXED_INCLUDES() =
343         addprefix(-I, $(INCLUDES))
344
345 .. index::
346    single: while
347 .. _label7.6:
348
349 7.6 スコープとエクスポート
350 ---------------------------------------
351 .. The OMake language is functional (apart from IO and shell commands). This comes in two parts: functions are first-class, and variables are immutable (there is no assignment operator). The latter property may seem strange to users used to GNU make, but it is actually a central point of OMake. Since variables can't be modified, it is impossible (or at least hard) for one part of the project to interfere with another.
352
353 OMakeの言語は(IOとシェルコマンドは除きますが)関数型言語となっています。これは、まず関数が最上級のものであることと、変数が不変なものである(代入という操作が存在しない)という2つから、そうであると言えるでしょう。後者に関しては、おそらく従来のGNU makeを使っていたユーザからすると奇妙なものに思えるかもしれません。しかしこれは実際にOMakeを使う上で非常に重要な点となります。変数は修正できませんので、プロジェクトの一部分が他の部分に干渉することは不可能(あるいは非常に困難)です。
354
355 .. To be sure, pure functional programming can be awkward. In OMake, each new indentation level introduces a new scope, and new definitions in that scope are lost when the scope ends. If OMake were overly strict about scoping, we would wind up with a lot of convoluted code.
356
357 これを従来の純粋な関数型言語のように実装してしまうと、非常に使いにくいものになるかもしれません。OMakeでは、インデントすることでレベルを一つ挙げた場合、新しいスコープが導入されます。そしてスコープが終わると、そのスコープで新しく定義された変数は消去されます。もしOMakeが馬鹿真面目にスコープに関して厳格な仕様であったなら、おそらくコードはもっと複雑なものになったでしょう。 ::
358
359    osh> X = 1
360    osh> setenv(BOO, 12)
361    osh> if $(equal $(OSTYPE), Win32)
362             setenv(BOO, 17)
363             X = 2
364    osh> println($X $(getenv BOO))
365    1 12
366
367 .. The export command presents a way out. It takes care of “exporting” a value (or the entire variable environment) from an inner scope to an outer one.
368
369 ``export`` コマンドはこの制限を外に出します。このコマンドは内部のスコープの値(あるいは全体の変数環境)を外部に『エクスポート』するお世話をします。 ::
370
371    osh> X = 1
372    osh> setenv(BOO, 12)
373    osh> if $(equal $(OSTYPE), Win32)
374             setenv(BOO, 17)
375             X = 2
376             export
377    osh> println($X $(getenv BOO))
378    2 17
379
380 .. Exports are especially useful in loop to export values from one iteration of a loop to the next.
381
382 エクスポートは、ループ中のイテレーションから次のイテレーションへ値をエクスポートするのに特に役立ちます。 ::
383
384    # オーケー、それでは配列の各成分を足し合わせてみよう
385    osh>sum(l) =
386            total = 0
387            foreach(i, $l)
388                total = $(add $(total), $i)
389            value $(total)
390    osh>sum(1 2 3)
391    - : 0 : Int
392
393    # おっと、正常に動いていないじゃないか!
394    osh>sum(l) =
395            total = 0
396            foreach(i, $l)
397                total = $(add $(total), $i)
398                export
399            value $(total)
400    osh>sum(1 2 3)
401    - : 6 : Int
402
403 .. A while loop is another form of loop, with an auto-export.
404
405 ``while`` ループは自動的にエクスポートしてくれる、別の形のループ文です。 ::
406
407     osh>i = 0
408     osh>total = 0
409     osh>while $(lt $i, 10)
410             total = $(add $(total), $i)
411             i = $(add $i, 1)
412     osh>println($(total))
413     45
414
415 .. index::
416    single: シェルエイリアス
417    single: Shell
418 .. _label7.7:
419
420 7.7 シェルエイリアス
421 ---------------------------------------
422 .. Sometimes you may want to define an alias, an OMake command that masquerades as a real shell command. You can do this by adding your function as a method to the Shell object.
423
424 ときどきあなたは *エイリアス* を定義したいと思うことがあるかもしれません。そのためにOMakeでは、実際にシェルコマンドが存在しているかのようにふるまうコマンドが存在します。あなたはこれを、 ``Shell`` オブジェクトに対象の関数を追加することで実現できます。
425
426 .. For an example, suppose we use the awk function to print out all the comments in a file.
427
428 例えば、 ``awk`` 関数を用いて、あるファイル中のすべてのコメントを出力する場合について考えてみましょう。 ::
429
430     osh>cat comment.om
431     # Comment function
432     comments(filename) =
433         awk($(filename))
434         case $'^#'
435             println($0)
436     # File finished
437     osh>include comment
438     osh>comments(comment.om)
439     # Comment function
440     # File finished
441
442 .. To add it as an alias, add the method (using += to preserve the existing entries in the Shell).
443
444 これをエイリアスとして追加するには、 ``Shell`` オブジェクトにメソッドを追加します。 ``+=`` を用いて、シェルの既存の内容を保存している点に注意してください。 ::
445
446    osh>Shell. +=
447            printcom(argv) =
448                comments($(nth 0, $(argv)))
449    osh>printcom comment.om > output.txt
450    osh>cat output.txt
451    # Comment function
452    # File finished
453
454 .. A shell command is passed an array of arguments argv. This does not include the name of the alias.
455
456 シェルコマンドは引数として配列 ``argv`` が渡されます。これはエイリアスの名前には *含まれていません* 。
457
458 .. index::
459    single: リダイレクション
460    single: stdin
461    single: stdout
462    single: stderr
463 .. _label7.8:
464
465 7.8 簡単に入出力のリダイレクションを行う
466 -----------------------------------------
467 .. As it turns out, scoping also provides a nice alternate way to perform redirection. Suppose you have already written a lot of code that prints to the standard output channel, but now you decide you want to redirect it. One way to do it is using the technique in the previous example: define your function as an alias, and then use shell redirection to place the output where you want.
468
469 結果的に、スコーピングによってリダイレクションの実行に関しての良い代替案も表れることとなりました。それでは、既に標準の出力先に出力するコードが大量にあるが、この出力先のリダイレクションを行いたいというような場合について考えてみましょう。まず一つ目の方法としては、前回のテクニックを用いることが挙げられます。具体的には、関数をエイリアスとして定義し、あなたが望む出力先にすることでシェルのリダイレクションを行うといった方法です。
470
471 .. There is an alternate method that is easier in some cases. The variables stdin, stdout, and stderr define the standard I/O channels. To redirect output, redefine these variables as you see fit. Of course, you would normally do this in a nested scope, so that the outer channels are not affected.
472
473 別の方法については、前者の方法よりも簡単な場合があります。変数 ``stdin`` ``stdout`` ``stderr`` は標準I/Oの出力先について定義しています。出力先をリダイレクトするには、これらの変数をあなたが望むように再定義します。もちろん、あなたはこれを普通にネストされたスコープ上で行うことができるので、外部の出力先に影響を与えることはありません。 ::
474
475     osh>f() =
476             println(Hello world)
477     osh>f()
478     Hello world
479     osh>section:
480             stdout = $(fopen output.txt, w)
481             f()
482             close($(stdout))
483     osh>cat output.txt
484     Hello world
485
486 .. This also works for shell commands. If you like to gamble, you can try the following example.
487
488 これはシェルコマンドに対しても同様です。もしあなたがギャンブル好きであるならば、以下の例を試してみるのもいいでしょう。 ::
489
490     osh>f() =
491             println(Hello world)
492     osh>f()
493     Hello world
494     osh>section:
495             stdout = $(fopen output.txt, w)
496             f()
497             cat output.txt
498             close($(stdout))
499     osh>cat output.txt
500     Hello world
501     Hello world
502