-
Notifications
You must be signed in to change notification settings - Fork 1
/
3language-basics.re
executable file
·4219 lines (2968 loc) · 200 KB
/
3language-basics.re
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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
= ClojureScript 入門
#@# Page11
#@# Language (the basics)
#@# This chapter will be a little introduction to ClojureScript without assumptions about previous knowledge of the Clojure language, providing a quick tour over all the things you will need to know about ClojureScript and understand the rest of this book.
#@# You can run the code snippets in the online interactive repl: http://www.ClojureScript.io
本章では、ClojureScript の概要を見ていきます。Clojure の知識は想定していません。4 章以降を理解するために必要なことを簡潔に説明します。オンラインの REPL@<fn>{repl1} でコードの動作を確認することができます。
//footnote[repl1][https://www.ClojureScript.io]
== Lisp 構文 の第一歩
#@# First steps with Lisp syntax
#@# Invented by John McCarthy in 1958, Lisp is one of the oldest programming languages that is rstill around. It has evolved into many derivatives called dialects, ClojureScript being one of them. It is a programming language written in its own data structures — originally lists enclosed in parentheses — but Clojure(Script) has evolved the Lisp syntax with more data structures, making it more pleasant to write and read.
Lisp は 1958 年に John McCarthy 氏 によって発明された最も古いプログラミング言語の 1 つです。現在も様々な分野で利用されており、Lisp 方言と呼ばれる多くの派生が進化してきました。CloureScript も Lisp 方言の 1 つです。元々 Lisp ではリストは丸括弧で囲われますが、Clojure(Script) では独自のデータ構造が実装されており、読み書きが容易です。
#@# A list with a function in the first position is used for calling a function in ClojureScript . In the example below, we apply the addition function to three arguments. Note that unlike in other languages, + is not an operator but a function. Lisp has no operators; it only has functions.
ClojureScript では、リストの 1 番目に関数がある場合、関数を呼び出すために使われます。次の例では加算する関数を 3 つの引数に適用させています。他の言語とは異なり、@<code>{+} は演算子ではなく関数であることに注意してください。Lisp には演算子はなく、関数しかありません。
//emlist{
(+ 1 2 3)
;; => 6
//}
#@# In the example above, we're applying the addition function + to the arguments 1 , 2 and 3. ClojureScript allows many unusual characters like ? or - in symbol names, which makes it easier to read:
上の例では、加算するための関数である @<code>{+} を @<code>{1}, @<code>{2}, @<code>{3} に適用しています。ClojureScript では @<code>{?} や @<code>{-} のような文字をシンボルの名前として利用できます。このことにより、ClojureScript で書かれたプログラムは読みやすくなっています。
//emlist{
(zero? 0)
;; => true
//}
#@# To distinguish function calls from lists of data items, we can quote lists to keep them from being evaluated. The quoted lists will be treated as data instead of as a function call:
関数の呼び出しとデータとを区別するために、リストの前にクオート @<code>{'} をつけます。クオートがつけられたリストは、関数の呼び出しではなく、データとして処理されます。
#@# Page12
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
//emlist{
'(+ 1 2 3) ;; => (+ 1 2 3)
//}
#@# ClojureScript uses more than lists for its syntax. The full details will be covered later, but here is an example of the usage of a vector (enclosed in brackets) for defining local bindings:
ClojureScript ではリスト以外の構文も使います。詳細な説明は後の章で行いますが、ベクタの使い方を例として取り上げます。ベクタは角括弧 @<code>{[ ]} で囲み、ローカルな束縛を定義します。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(let [x 1
y 2
z 3]
(+ x y z))
;; => 6
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# This is practically all the syntax we need to know for using not only ClojureScript , but any Lisp . Being written in its own data structures (often referred to as _homoiconicity_) is a great property since the syntax is uniform and simple; also, code generation via xref:macros-section[macros] is easier than in any other language, giving us plenty of power to extend the language to suit our needs.
以上が ClojureScript でプログラムを書く上で必要となる構文の全てです。他の Lisp 方言でプログラムを書く場合も同様です。独自のデータ構造でプログラミング言語が実装されていることは、構文に統一性があり simple なので、素晴らしい特徴だといえます。マクロでコードを生成することも他の言語と比べて簡単であり、私たちのニーズに合わせて言語を拡張するのに十分な力を与えてくれます。
== 基本的なデータ型
#@# The base data types
#@# The ClojureScript language has a rich set of data types like most programming languages. It provides scalar data types that will be very familiar to you, such as numbers, strings, and floats. Beyond these, it also provides a great number of others that might be less familiar, such as symbols, keywords, regexes (regular expressions), variables, atoms, and volatiles.
他のプログラミング言語と同様、ClojureScript には多くのデータ型が用意されています。ClojureScript には、数値、文字列、浮動小数などのスカラー型のデータ構造があります。これら以外にも、シンボル、キーワード、正規表現、変数、アトム、Volatile などのデータ構造もあります。
#@# ClojureScript embraces the host language, and where possible, uses the host's provided types. For example: numbers and strings are used as is and behave in the same way as in JavaScript .
ClojureScript はホスト言語を採用し、可能な限りホスト言が提供する型を使用します。例えば、数値と文字列は、JavaScript の数値と文字列と同じように利用して、結果を得ることができます。
=== 数値
#@# Numbers
#@# In ClojureScript , numbers include both integers and floating points. Keeping in mind that ClojureScript is a guest language that compiles to JavaScript , integers are actually JavaScript 's native floating points under the hood.
#@# As in any other language, numbers in ClojureScript are represented in the following ways:
ClojureScript において、数値は整数と浮動小数点数を含みます。ClojureScript は JavaScript にコンパイルされる言語だということを覚えておいてください。整数は JavaScript では浮動小数点数になります。他の言語と同じように、ClojureScript で数値は次のように表現されます。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
23
+23
-100
1.7
-2
33e8
12e-14
3.2e-4
//}
#@# Page13
#@# @<embed>{|latex|\vspace{-0.5\Cvs\}}
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
=== キーワード
#@# Keywords
#@# Keywords in ClojureScript are objects that always evaluate to themselves. They are usually used in <<maps-section,map data structures>> to efficiently represent the keys.
ClojureScript においてキーワードは、常にキーワードへ評価されるオブジェクトです。マップのデータ構造でキーを効率よく表すために使われます。
//emlist{
:foobar ;; => :foobar
:2 ;; => :2
:? ;; => :?
//}
#@# As you can see, the keywords are all prefixed with :, but this character is only part of the literal syntax and is not part of the name of the object.
#@# You can also create a keyword by calling the keyword function. Don't worry if you don't understand or are unclear about anything in the following example;<<function-section,functions>> are discussed in a later section.
キーワードはリテラルとしてコロン @<code>{:} を使います。コロンはオブジェクトの名前の一部ではありません。
@<code>{keyword} 関数によりキーワードを作成することも可能です。以下の例は、今は理解できなくても構いません。後に関数の章で取り上げます。
//emlist{
(keyword "foo")
;; => :foo
//}
#@# When prefixing keywords with a double colon ::, the keyword will be prepended by the name of the current namespace. Note that namespacing keywords affects equality comparisons.
キーワードをダブルコロン @<code>{::} で始めると、キーワードの前に現在の名前空間が付きます。名前空間付きのキーワードは、等価性の比較に影響を与えるので注意してください。
//emlist{
::foo
;; => :cljs.user/foo
(= ::foo :foo)
;; => false
//}
#@# Another alternative is to include the namespace in the keyword literal, this is useful when creating namespaced keywords for other namespaces:
別の方法としては、リテラルに名前空間を含める方法もあります。この方法は、他の名前空間に名前空間付きのキーワードを作成する際に役に立ちます。
//emlist{
:cljs.unraveled/foo
;; => :cljs.unraveled/foo
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# The keyword function has an arity- 2 var iant where we can specify the namespace as the first parameter:
@<code>{keyword} 関数は 2 つの引数をとることができます。第 1 引数で名前空間を指定します。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
(keyword "cljs.unraveled" "foo")
;; => :cljs.unraveled/foo
//}
#@# Page14
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
=== シンボル
#@# Symbols
#@# Symbols in ClojureScript are very, very similar to *keywords* (which you now know about). But instead of evaluating to themselves, symbols are evaluated to something that they refer to, which can be functions, var iables, etc.
ClojureScript のシンボルはキーワードとよく似ていますが、自分自身に対して評価されるのではなく、シンボルが参照している対象(関数や変数等)に対して評価されます。
#@# Symbols start with a non numeric character and can contain alphanumeric characters as well as *, +, !, -, _, ', and ? such as :
シンボルの名前はアルファベットで始まり、記号(@<code>{*}, @<code>{+}, @<code>{!}, @<code>{-}, @<code>{_}, @<code>{'}, @<code>{?}) を含むことができますが、数字で始めることはできません。
//emlist{
sample-symbol
othersymbol
f1
my-special-swap!
//}
#@# Don't worry if you don't understand right away; symbols are used in almost all of our examples, which will give you the opportunity to learn more as we go on.
理解できなかったとしても気にしないでください。シンボルは様々な例で使われており、読み進むにつれて理解が深まります。
=== 文字列
#@# Strings
#@# There is almost nothing new we can explain about strings that you don't already know. In ClojureScript , they work the same as in any other language. One point of interest, however, is that they are immutable.
#@# In this case they are the same as in JavaScript :
文字列については特に説明することはありません。ClojureScript は、他の言語と同じように動作します。ただし、文字列が不変である点に注意してください。
この点は JavaScript と同じです。
//emlist{
"An example of a string"
//}
#@# One peculiar aspect of strings in ClojureScript is due to the language's Lisp syntax: single and multiline strings have the same syntax:
ClojureScript の文字列で特異な点は、Lisp の構文に由来するものです。文字列の構文は 1 行でも複数行でも同じです。
//emlist{
"This is a multiline
string in ClojureScript."
//}
=== 文字
#@# Characters
#@# ClojureScript also let s you write single characters using Clojure's character literal syntax.
リテラルで文字を書くこともできます。
//emlist{
\a ; 小文字の文字
\newline ; 改行文字
//}
#@# Since the host language doesn't contain character literals, ClojureScript characters are transformed behind the scenes into single character JavaScript strings.
ホスト言語の JavaScript では文字のリテラルを使えないので、ClojureScript の文字は、JavaScript の文字列の 1 文字に変換されます。
#@# Page15
//embed[latex]{
\enlargethispage{10mm}
//}
//embed[latex]{
\clearpage
//}
=== コレクション
#@# Collections
#@# Another big step in explaining a language is to explain its collections and collection abstractions. ClojureScript is not an exception to this rule.
#@# ClojureScript comes with many types of collections. The main difference between ClojureScript collections and collections in other languages is that they are persistent and immutable.
#@# Before moving on to these (possibly) unknown concepts, we'll present a high-level overview of existing collection types in ClojureScript .
あるプログラミング言語について詳しく知るためには、その言語でコレクションがどのように抽象化されているかを知る必要があり、ClojureScript にも当てはまります。
ClojureScript のコレクションには多くの型があります。ClojureScript が他の言語のコレクションと違うのは、コレクションが永続的で不変であることです。
詳しい説明に入る前に ClojureScript のコレクションに存在する型について概要を見ましょう。
===== リスト
#@# Lists
#@# This is a classic collection type in languages based on Lisp . Lists are the simplest type of collection in ClojureScript . Lists can contain items of any type, including other collections.
#@# Lists in ClojureScript are represented by items enclosed between parentheses:
リストは Lisp 系言語で典型的なコレクションの型です。リストは ClojureScript で最もシンプルなコレクションです。リストはどの型の要素を含むことができます。リストに他のコレクションを含むこともできます。リストは要素を丸括弧で囲みます。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
'(1 2 3 4 5)
'(:foo :bar 2)
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# As you can see, all list examples are prefixed with the ' char. This is because lists in Lisp -like languages are often used to express things like function or macro calls. In that case, the first item should be a symbol that will evaluate to something callable, and the rest of the list elements will be function arguments. However, in the preceding examples, we don't want the first item as a symbol; we just want a list of items.
上記の例では、リストの先頭にクオート @<code>{'} がついています。これは Lisp 系言語では、リストが関数やマクロの呼び出しに使われるためです。リストを関数やマクロの呼び出しに使う場合、初めの要素は関数やマクロのシンボル、残りの要素はその引数である必要があります。上の例ではリストの先頭にクオートがついているため、要素のリストとして扱われます。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# The following example shows the difference between a list without and with the preceding single quote mark:
リスト先頭にクオート @<code>{'} があるかどうかで、動作がどう違うかを確認しましょう。
//emlist{
(inc 1)
;; => 2
'(inc 1)
;; => (inc 1)
//}
#@# As you can see, if you evaluate `(inc 1)` without prefixing it with ', it will resolve the inc symbol to the *inc* function and will execute it with 1 as the first argument, returning the value 2 .
先頭にクオートをつけずに @<code>{(inc 1)} として評価した場合、@<code>{inc} シンボルは inc 関数として評価されます。@<code>{1} が第 1 引数として評価されて、@<code>{2} という値が返ります。
#@# You can also explicitly create a list with the list function:
リストを作るために、明示的に @<code>{list} 関数を使うことも可能です。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
(list 1 2 3 4 5)
;; => (1 2 3 4 5)
(list :foo :bar 2)
;; => (:foo :bar 2)
//}
#@# Lists have the peculiarity that they are very efficient if you access them sequentially or access their first elements, but a list is not a very good option if you need random (index) access to its elements.
リストは、前から順に要素にアクセスするには効率よく処理できますが、リスト内の要素に対してランダムに(もしくは特定のインデックスに)アクセスするのは不得意です。
#@# Page16
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
===== ベクタ
#@# Vectors
#@# Like lists, *vectors* store a series of values, but in this case, with very efficient index access to their elements, as opposed to lists, which are evaluated in order. Don't worry; in the following sections we'll go in depth with details, but at this moment, this simple explanation is more than enough.
#@# Vectors use square brackets for the literal syntax; let 's see some examples:
リストのようにベクタも連続する値を保存しますが、インデックスを用いて効率よく要素にアクセスできます。要素が前から順に評価されるリストと対照的です。後に詳しく説明しますが、現状ではこの程度の理解で十分です。ベクタはリテラルのために角括弧を使います。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
[:foo :bar]
[3 4 5 nil]
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# Like lists, vectors can contain objects of any type, as you can observe in the preceding example.
#@# You can also explicitly create a vector with the vector function, but this is not commonly used in ClojureScript programs:
リストと同様に、ベクタはどの型のオブジェクトを含むことができます。@<code>{vector} 関数を用いてベクタを作成できますが、あまり一般的ではありません。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
(vector 1 2 3)
;; => [1 2 3]
(vector "blah" 3.5 nil)
;; => ["blah" 3.5 nil]
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
===== マップ
#@# Maps
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# Maps are a collection abstraction that allow you to store key/value pairs. In other languages, this type of structure is commonly known as a hash-map or dict(dictionary). Map literals in ClojureScript are written with the pairs between curly braces.
マップはコレクションの 1 つであり、キーと値をセットで保存します。他の言語では、連想配列や辞書と言われるデータ構造です。
//emlist{
{:foo "bar", :baz 2 }
{:alphabet [:a :b :c]}
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# NOTE: Commas are frequently used to separate a key-value pair, but they are comp let ely optional. In ClojureScript syntax, commas are treated like spaces.
キーと値を分けるためにコンマを使うかどうかは任意です。ClojureScript の構文では、コンマはスペースとして処理されます。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# Like vectors, every item in a map literal is evaluated before the result is stored in a map, but the order of evaluation is not guaranteed.
ベクタのように、マップリテラルの各々の要素は、結果がマップに保存される前に毎回評価されます。ただし、要素が順に評価されるかは保証されません。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
===== セット
#@# Sets
#@# Sets store zero or more unique items of any type and are unordered. Like maps, they use curly braces for their literal syntax, with the difference being that they use a `#` as the leading character. You can also use the set function to convert a collection to a set:
最後はセットです。セットは任意の型のデータを 0 個以上保存することができますが、要素間に順序はありません。セットのためには、マップのように波括弧 @<code>${ }$ を使います。波括弧の前に シャープ @<code>{#} をつける点がマップとは異なります。@<code>{set}関数を用いてコレクションをセットに変換することもできます。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
//emlist{
#{1 2 3 :foo :bar}
;; => #{1 :bar 3 :foo 2}
(set [1 2 1 3 1 4 1 5])
;; => #{1 2 3 4 5}
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# In subsequent sections, we'll go in depth about sets and the other collection types you've seen in this section.
後のセクションでは、セットと他のコレクションの型について詳しくみます。
#@# Page17
//embed[latex]{
\enlargethispage{10mm}
//}
//embed[latex]{
\clearpage
//}
== vars
#@# vars
#@# ClojureScript is a mostly functional language that focuses on immutability. Because of that, it does not have the concept of var iables as you know them in most other programming languages. The closest analogy to variables are the variables you define in algebra; when you say `x == 6` in mathematics, you are saying that you want the symbol x to stand for the number six.
ClojureScript は関数型プログラミング言語であり、不変性に重点をおいています。そのため、他の言語の変数にあたる概念がありません。代数学における変数にあたる概念はあります。つまり数学で@<code>{x = 6}というときには、@<code>{x}というシンボルが 6 を表すということを意味します。
#@# In ClojureScript , var s are represented by symbols and store a single value together with metadata.
#@# You can define a var using the def special form:
ClojureScript において var はシンボルで表現されて、メタデータと一緒に 1 つの値を保存します。特殊形式の @<code>{def} を使うことで、var を 1 つ定義することができます。
//emlist{
(def x 2 2)
(def y [1 2 3])
//}
#@# var s are always top level in the namespace (<<namespace-section,which we will explain later>>). If you use def in a function call, the var will be defined at the namespace level, but we do not recommend this - instead, you should use let to define var iables within a function.
var は名前空間において常にトップレベルです。名前空間については後に詳しく説明します。もし@<code>{def}を関数の呼び出しの中で使う場合、var は名前空間のレベルに定義されますが、これは推奨されません。関数の中で変数を定義するには@<code>{let}を使うことが推奨されます。
== 関数
#@# Functions
=== はじめの一歩
#@# The first contact
#@# It's time to make things happen. ClojureScript has what are known as first class functions. They behave like any other type; you can pass them as parameters and you can return them as values, always respecting the lexical scope. ClojureScript also has some features of dynamic scoping, but this will be discussed in another section.
ClojureScript には第一級関数と呼ばれるものがあります。第一級の関数は、他の型と同じように使えます。例えば、常にレキシカルスコープを重視しながら、関数の引数として渡せたり、関数の返り値として利用することができます。ClojureScript におけるダイナミックスコープについては別のセクションで扱います。
#@# If you want to know more about scopes, this link:http://en.wikipedia.org/wiki/Scope_(computer_science)[Wikipedia article] is very extensive and explains different types of scoping.
スコープについて詳しく知るには、http://en.wikipedia.org/wiki/Scope を参考にしてください。様々なタイプのスコープについて詳細を説明しています。
#@# As ClojureScript is a Lisp dialect, it uses the prefix notation for calling a function:
ClojureScript は Lisp 方言の 1 つであり、関数の呼び出しは、次のように前置記法を用います。
//emlist{
(inc 1)
;; => 2
//}
#@# In the example above, inc is a function and is part of the ClojureScript runtime, and 1 is the first argument for the inc function.
この例では@<code>{inc}は関数であり、実行時に利用できる関数の 1 つです。この場合、@<code>{1} は@<code>{inc}関数の第 1 引数です。
//emlist{
(+ 1 2 3)
;; => 6
//}
#@# Page18
//embed[latex]{
\enlargethispage{0mm}
//}
//embed[latex]{
\clearpage
//}
#@# The + symbol represents an add function. It allows multiple parameters, whereas in ALGOL-type languages, + is an operator and only allows two parameters.
@<code>{+} シンボルは加算を意味します。複数の引数をとることができる点ができ、ALGOL型のプログラミング言語が 2 つの引数しかとることができないことと対照的です。
#@# The prefix notation has huge advantages, some of them not always obvious. ClojureScript does not make a distinction between a function and an operator; everything is a function. The immediate advantage is that the prefix notation allows an arbitrary number of arguments per "operator". It also comp let ely eliminates the problem of operator precedence.
前置記法には大きな利点があり、その中には必ずしも明白でないものもあります。ClojureScript では関数とオペレータを区別しません。全てが関数です。すぐに分かる長所としては、前置記法ではオペレータが任意の数の引数を許容することです。また、演算子の優先順位の問題も解消されます。
=== 自作関数の定義
#@# Defining your own functions
#@# You can define an unnamed (anonymous) function with the fn special form. This is one type of function definition; in the following example, the function takes two parameters and returns their average.
特殊形式の @<code>{fn} を用いると、無名関数を定義することができます。次の例では、関数は 2 つの引数を取り、それらの平均を返します。
//emlist{
(fn [param1 param2]
(/ (+ param1 param2) 2.0))
//}
#@# You can define a function and call it at the same time (in a single expression):
関数を定義して即時に呼び出すことができます(1 つの式で)。
//emlist{
((fn [x] (* x x)) 5)
;; => 25
//}
#@# let 's start creating named functions. But what does a _named function_ really mean? It is very simple; in ClojureScript , functions are first-class and behave like any other value, so naming a function is done by simply binding the function to a symbol:
次に名前付き関数を作成しましょう。名前付き関数とはどういうことでしょうか。ClojureScript ではすごくシンプルです。関数は第一級クラスであり、他の全ての値と同じように振る舞います。関数をシンボルに束縛することにより、関数に名前をつけます。
//emlist{
(def square (fn [x] (* x x)))
(square 12)
;; => 144
//}
#@# ClojureScript also offers the defn macro as a little syntactic sugar for making function definition more idiomatic:
ClojureScript には、関数定義の糖衣構文として @<code>{defn} マクロがあります。
//emlist{
(defn square
"特定の数字の2乗を返す"
[x]
(* x x))
//}
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# The string that comes between the function name and the parameter vector is called a _docstring_ (documentation string); programs that automatically create web documentation from your source files will use these docstrings.
関数名と引数の間にある文字列は docstring(documentation string) と呼ばれます。Webでドキュメントを自動生成するときに docstring が使われます。
#@#??docstring -> 孔雀本では「ドキュメント文字列」と訳されている。
@<embed>{|latex|\vspace{-0.2\Cvs\}}
#@# Page19
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
=== 多様な Arity をもつ関数
#@# Functions with multiple arities
#@# ClojureScript also comes with the ability to define functions with an arbitrary number of arguments. (The term _arity_ means the number of arguments that a function takes.) The syntax is almost the same as for defining an ordinary function, with the difference that it has more than one body.
#@# let 's see an example, which will explain it better:
ClojureScript は任意の数の引数をとる関数を定義することができます。( Arity という用語は関数が受ける引数の数を意味します) そのための構文は普通の関数定義と大体同じですが、複数の本体をもつ点が異なります。
例をみてみましょう。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(defn myinc
"自己定義版のパラメータ化された inc"
([x] (myinc x 1))
([x increment] (+ x increment)))
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# This line: `([x] (myinc x 1))` says that if there is only one argument, call the function myinc with that argument and the number 1 as the second argument. The other function body `([x increment] (+ x increment))` says that if there are two arguments, return the result of adding them.
#@# Here are some examples using the previously defined multi-arity function. Observe that if you call a function with the wrong number of arguments, the compiler will emit an error message.
@<code>{([x] (myinc x 1))} は、もし引数が 1 つの場合、@<code>{myinc} 関数に @<code>{x} を第 1 引数、@<code>{1} を第 2 引数として渡すということを表しています。@<code>{([x increment] (+ x increment))} は、もし引数が 2 つの場合、2 つの引数を足した結果を返します。
ここで定義した関数を使ってみましょう。引数の数を間違えて関数を呼び出すと、コンパイラからエラーメッセージが出力されることに注目してください。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(myinc 1)
;; => 2
(myinc 1 3)
;; => 4
(myinc 1 3 3)
;; Compiler error
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# NOTE: Explaining the concept of "arity" is out of the scope of this book, however you can read about that in this link:http://en.wikipedia.org/wiki/Arity[Wikipedia article].
Arity の概念を本書で説明することは、本書の範囲を超えています。詳しくは Wikipedia の Arity のページを参照してください。
=== 可変長引数関数
#@# variadic functions
#@# Another way to accept multiple parameters is defining var iadic functions. var iadic functions are functions that accept an arbitrary number of arguments:
可変長引数をとる関数を定義することでも、複数の引数を受け取る関数を定義することができます。可変長引数をとる関数は、任意の数の引数をとることができます。
#@# The way to denote a var iadic function is using the & symbol prefix on its arguments vector.
可変長引数関数を定義するには @<code>{&} シンボルを引数のベクタにつけます。
@<embed>{|latex|\vspace{-0.3\Cvs\}}
//emlist{
(defn my-variadic-set
[& params]
(set params))
(my-variadic-set 1 2 3 1)
;; => #{1 2 3}
//}
@<embed>{|latex|\vspace{-0.3\Cvs\}}
#@# Page20
//embed[latex]{
\enlargethispage{10mm}
//}
//embed[latex]{
\clearpage
//}
=== 無名関数の短い構文
#@# Short syntax for anonymous functions
#@# ClojureScript provides a shorter syntax for defining anonymous functions using the `#()` reader macro (usually leads to one-liners). Reader macros are "special" expressions that will be transformed to the appropriate language form at compile time; in this case, to some expression that uses the fn special form.
ClojureScript では、無名関数のためのシンプルな構文としてリーダマクロの @<code>{#()} を使うことができます(ワンライナーを書くためによく用いられます)。リーダーマクロとは、コンパイル時に適当なフォームに変換される「特別な」表現方法です。この場合、@<code>{fn}のフォームに変換されます。
//emlist{
(def average #(/ (+ %1 %2) 2))
(average 3 4)
;; => 3.5
//}
#@# The preceding definition is shorthand for:
この @<code>{average} の定義は、次のように展開されます。
//emlist{
(def average-longer (fn [a b] (/ (+ a b) 2)))
(average-longer 7 8)
;; => 7.5
//}
#@# The % 1 , % 2 ... %N are simple markers for parameter positions that are implicitly declared when the reader macro will be interpreted and converted to a fn expression.
@<code>{%1} や @<code>{%2} は引数の位置を示す印であり、リーダーマクロが@<code>{fn}の式に変換される時に暗黙的に宣言されます。
#@# If a function only accepts one argument, you can omit the number after the % symbol, e.g., a function that squares a number: `#(* % 1 % 1))` はcan be written `++#++(* % %))`.
もし関数が 1 つしか引数を取らない場合、@<code>{%} シンボルの後の数字は省略できます。例えば、@<code>{#(* %1 %1)} は @<code>{#(* % %)} と書くことができます。
#@# Additionally, this syntax also supports the var iadic form with the %& symbol:
さらに @<code>{%&} シンボルにより可変長引数にすることができます。
//emlist{
(def my-variadic-set #(set %&))
(my-variadic-set 1 2 2)
;; => #{1 2}
//}
== フロー制御
#@# Flow control
#@# ClojureScript has a very different approach to flow control than languages like JavaScript , C, etc.
ClojureScript のフロー制御は、JavaScript や C などとアプローチが異なります。
=== if による条件分岐
#@# Branching with if
#@# let 's start with a basic one: if. In ClojureScript , the if is an expression and not a statement, and it has three parameters: the first one is the condition expression, the second one is an expression that will be evaluated if the condition expression evaluates to logical true, and the third expression will be evaluated otherwise.
ClojureScript において @<code>{if} は文ではなく式であり、3 つの引数をとります。1 つ目は条件式、2 つ目は条件が真の場合に評価される式、3 つ目は条件が偽の場合に評価される式です。
#@# Page21
//embed[latex]{
\enlargethispage{10mm}
//}
//embed[latex]{
\clearpage
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(defn discount
"1点以上の購入で5%割引されます"
[quantity]
(if (>= quantity 100)
0.05
0))
(discount 30)
;; => 0
(discount 130)
;; => 0.05
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# The block expression do can be used to have multiple expressions in an if branch. xref:block-section[do is explained in the next section].
@<code>{if} の条件分岐の中で複数の式を実行するには @<code>{do} を使います。@<code>{do}については次のセクションで説明します。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
=== cond による条件分岐
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# Sometimes, the if expression can be slightly limiting because it does not have the "else if" part to add more than one condition. The cond macro comes to the rescue.
#@# With the cond expression, you can define multiple conditions:
@<code>{if}式には複数の条件を追加するための @<code>{else if} の部分がないため、多少制限されますが、@<code>{cond} マクロでこの点を解決できます。@<code>{cond}では複数の条件を定義できます。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(defn mypos?
[x]
(cond
(> x 0) "positive"
(< x 0) "negative"
:else "zero"))
(mypos? 0) ;; => "zero"
(mypos? -2) ;; => "negative"
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# Also, cond has another form, called condp, that works very similarly to the simple cond but looks cleaner when the condition (also called a predicate) is the same for all conditions:
また、@<code>{cond}には @<code>{condp} と呼ばれる別の形式もあり、単純な@<code>{cond}と非常によく似た働きをしますが、条件(述語とも呼ばれます)が全ての条件に対して同じ場合は、より綺麗に見えます。
#@# The line `condp = (keyword code)` means that, in each of the following lines, ClojureScript will apply the = function to the result of evaluating `(keyword code)`.
以下の各行では、ClojureScript は @<code>{(keyword code)} を評価した結果に @<code>{=} 関数を適用します。
@<embed>{|latex|\vspace{-0.4\Cvs\}}
//emlist{
(defn translate-lang-code
[code]
(condp = (keyword code)
:es "Spanish"
:en "English"
"Unknown"))
(translate-lang-code "en")
;; => "English"
(translate-lang-code "fr")
;; => "Unknown"
//}
@<embed>{|latex|\vspace{-0.4\Cvs\}}
#@# Page22
//embed[latex]{
\enlargethispage{20mm}
//}
//embed[latex]{
\clearpage
//}
=== case による条件分岐
#@# The case branching expression has a similar use as our previous example with condp. The main differences are that case always uses the == predicate/function and its branching values are evaluated at compile time. This results in a more performant form than cond or condp but has the disadvantage that the condition value must be static.
#@# Here is the previous example rewritten to use case:
@<code>{case} は、前例の@<code>{condp}と同様の使い方をします。主な違いは、常に @<code>{=} 述語(関数)が使用されて、その分岐値がコンパイル時に評価されることです。そのため @<code>{cond}や@<code>{condp}よりもパフォーマンスが良いですが、条件の値が静的でなければならないという欠点があります。
@<embed>{|latex|\vspace{-0.3\Cvs\}}
//emlist{
(defn translate-lang-code
[code]
(case code
"es" "Spanish"
"en" "English"
"Unknown"))
(translate-lang-code "en")
;; => "English"
(translate-lang-code "fr")
;; => "Unknown"
//}
== 真偽判定
#@# Truthiness
#@# This is the aspect where each language has its own semantics (mostly wrongly). The majority of languages consider empty collections, the integer 0, and other things like this to be false. In ClojureScript , unlike in other languages, only two values are considered as false: nil and false. Everything else is treated as logical true.
真偽判定はプログラミング言語によりセマンティクスが異なります。多くの言語では、空のコレクションや整数の @<code>{0} 、またこれらと同様の値を偽と見なします。ClojureScript では @<code>{nil} と @<code>{false} だけが偽と見なされ、その他は論理的に真として扱われます。
#@# Jointly with the ability to implement the callable protocol (the IFn, explained more in detail later), data structures like sets can be used just as predicates, without need of additional wrapping them in a function:
callable プロトコル(@<code>{IFn} については後述)を実装する能力と一緒に、集合のようなデータ構造は、関数の中でそれらを追加的にラップする必要なしに、述語として使うことができます。
@<embed>{|latex|\vspace{-0.3\Cvs\}}
//emlist{
(def valid? #{1 2 3})
(filter valid? (range 110))
;; => (1 2 3)
//}
#@# This works because a set returns either the value itself for all contained elements or nil:
このように動作するのは、セットが全ての要素の値自体か @<code>{nil} を返すためです。
@<embed>{|latex|\vspace{-0.3\Cvs\}}
//emlist{
(valid? 1)
;; => 1
(valid? 4)
;; => nil
//}
@<embed>{|latex|\vspace{-0.3\Cvs\}}
#@# Page23
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
== ローカル、ブロック、ループ
#@# Locals, Blocks, and Loops
=== ローカル
#@# Locals
#@# ClojureScript does not have the concept of var iables as in ALGOL-like languages, but it does have locals. Locals, as per usual, are immutable, and if you try to mutate them, the compiler will throw an error.
ClojureScript には ALGOL のような変数の概念がありませんが、ローカル(local)はあります。ローカルは不変であり、変更しようとするとエラーが発生します。
#@# Locals are defined with the let expression. The expression starts with a vector as the first parameter followed by an arbitrary number of expressions. The first parameter (the vector) should contain an arbitrary number of pairs that give a _binding form_ (usually a symbol) followed by an expression whose value will be bound to this new local for the remainder of the let expression.
ローカルは @<code>{let} 式で定義されます。@<code>{let}式は、最初のパラメータとしてベクタで始まり、その後に任意の数の式が続きます。最初のパラメータのベクタには束縛フォームを与えて、その @<code>{let} 内のローカルで有効な名前と値のペアを宣言します。
//emlist{
(let [x (inc 1)
y (+ x 1)]
(println "Simple message from the body of a let")
(* x y))
//}
#@# In the preceding example, the symbol x is bound to the value `(inc 1)`, which comes out to 2 , and the symbol y is bound to the sum of x and 1 , which comes out to 3. Given those bindings, the expressions `(println "Simple message from the body of a let ")` and `(* x y)` are evaluated.
上の例では、シンボル @<code>{x} が @<code>{(inc 1)} の値に束縛されて、シンボル @<code>{y} が @<code>{x} と 1 の合計(つまり 3 )に束縛されます。これらの束縛を受けて、 @<code>{(println "Simple message from the body of a let")} と @<code>{(* x y)} が評価されます。
=== ブロック
#@# In JavaScript , braces `{` and `}` delimit a block of code that “belongs together”. Blocks in ClojureScript are created using the do expression and are usually used for side effects, like printing something to the console or writing a log in a logger.
#@# A side effect is something that is not necessary for the return value.
JavaScript において波括弧 @<code>${ }$ は「共に属する」コードのブロックを決めます。ClojureScript では @<code>{do} を用いてブロックを作成します。@<code>{do}はコンソールの何かの結果を出力したり、ログを出力したりするような、副作用を伴う場合に使います。副作用とは、戻り値には不要なものをいいます。
#@# The do expression accepts as its parameter an arbitrary number of other expressions, but it returns the return value only from the last one:
@<code>{do}は任意の数の式を含むことができますが、最後に評価された式の値が返り値となります。
//emlist{
(do
(println "hello world")
(println "hola mundo")
;; この値は返却されずに捨てられます。
(* 3 5)
(+ 1 2))
;; hello world
;; hola mundo
;; => 3
//}
#@# The body of the let expression, explained in the previous section, is very similar to the do expression in that it allows multiple expressions. In fact, the let has an implicit do.
先ほど説明した@<code>{let}の本体は、複数の式をもつことができる点において @<code>{do} とよく似ています。実際、@<code>{let} は暗黙の @<code>{do} をもちます。
#@# Page24
//embed[latex]{
\enlargethispage{15mm}
//}
//embed[latex]{
\clearpage
//}
=== ループ
#@# loops
#@# The functional approach of ClojureScript means that it does not have standard, well-known, statement-based loops such as for in JavaScript . The loops in ClojureScript are handled using recursion. Recursion sometimes requires additional thinking about how to model your problem in a slightly different way than imperative languages.
ClojureScript は関数型のアプローチを採用しているので、JavaScript での @<code>{for} のような一般的なループがありません。ClojureScript のループは再帰を使って処理されます。再帰を用いてプログラムを書くためには、命令型のプログラミング言語とは少し違った方法で問題をモデル化する必要があります。
#@#(参)モデル化: http://e-words.jp/w/%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0.html
#@# Many of the common patterns for which for is used in other languages are achieved through higher-order functions - functions that accept other functions as parameters.
他の言語で @<code>{for} が使われるパターンの多くは、高階関数を用いて置き換えることができます。高階関数とは関数を引数として受け取る関数です。
===== loop/recur によるループ
#@# Looping with loop/recur
#@# let 's take a look at how to express loops using recursion with the loop and recur forms. loop defines a possibly empty list of bindings (notice the symmetry with let ) and recur jumps execution back to the looping point with new values for those bindings.
#@# let 's see an example:
では、@<code>{loop} と @<code>{recur} を用いた再帰でループを表現する方法を見てみましょう。
@<code>{loop} は、空の可能性のある束縛のリスト(@<code>{let}との対称性に注目してください)を定義して、繰り返し実行すると、それらの束縛の新しい値を使ってループの開始点に戻ります。例を見てみましょう。
//emlist{
(loop [x 0]
(println "Looping with " x)
(if (= x 2)
(println "Done looping!")
(recur (inc x))))
;; Looping with 0
;; Looping with 1
;; Looping with 2
;; Done looping!
;; => nil
//}
#@# In the above snippet, we bind the name x to the value 0 and execute the body. Since the condition is not met the first time, it's rerun with recur, incrementing the binding value with the inc function. We do this once more until the condition is met and, since there aren't any more recur calls, exit the loop.
上の例では、まず @<code>{x} を @<code>{0} に束縛して本体を実行します。@<code>{if} の条件が満たされていないので、@<code>{(recur (inc x))} で @<code>{inc} で @<code>{x} に @<code>{1} が加算されてループが再実行されます。条件が満たされると @<code>{recur} の呼び出しが止まり、ループが終了します。
#@# Note that loop isn't the only point we can recur to; using recur inside a function executes the body of the function recursively with the new bindings:
@<code>{recur} を使うことができるのは @<code>{loop} だけではありません。関数の中で @<code>{recur} を使用すると、新しい束縛値で本体が再帰的に実行されます。
@<embed>{|latex|\vspace{-0.3\Cvs\}}
//emlist{
(defn recursive-function
[x]
(println "Looping with" x)
(if (== x 2)
(println "Done looping!")
(recur (inc x))))
(recursive-function 0)
;; Looping with 0
;; Looping with 1
;; Looping with 2
;; Done looping!
;; => nil
//}
#@# Page25
//embed[latex]{
\enlargethispage{20mm}
//}
//embed[latex]{
\clearpage
//}
===== 高階関数によるループの置き換え
#@# In imperative programming languages it is common to use for loops to iterate over data and transform it, usually with the intent being one of the following:
命令型プログラミング言語では、@<code>{for} で反復的にデータを変形しますが、次のような目的で利用することが多いです。
命令型プログラミング言語では、@<code>{for} ループを使用してデータを繰り返し変換することが一般的です。通常、次のいずれかを目的とします。
#@# - Transform every value in the iterable yielding another iterable
#@# - Filter the elements of the iterable by certain criteria
#@# - Convert the iterable to a value where each iteration depends on the result from the previous one
#@# - Run a computation for every value in the iterable
//embed[latex]{
\vspace{1em}
//}
- イテラブルの全ての値を、別のイテラブルに変形する
- ある条件でイテラブルの要素をフィルターする
- イテラブルの要素を順に処理をして 1 つの値に変換する
- イテラブルにある各々の値を計算する
//embed[latex]{
\vspace{1em}
//}
#@# The above actions are encoded in higher-order functions and syntactic constructs in ClojureScript ; let 's see an example of the first three.
上記の実行は、高階関数と ClojureScript の構文を用いて書くことができます。まず最初の3つの例を見ていきましょう。
#@# For transforming every value in an iterable data structure we use the map function, which takes a function and a sequence and applies the function to every element:
イテラブルにある全ての値を変換するには @<code>{map} 関数を使います。@<code>{map} 関数は、関数とシーケンスを引数にとり、関数をシーケンスの各要素に適用します。
//emlist{
(map inc [0 1 2])
;; => (1 2 3)
//}
#@# The first parameter for map can be _any_ function that takes one argument and returns a value. For example, if you had a graphing application and you wanted to graph the equation `y&# 1 60;==&# 1 60;3x&# 1 60;+&# 1 60;5` for a set of _x_ values, you could get the _y_ values like this:
@<code>{map} 関数の初めのパラメータには、1 つの引数をとり 1 つの値を返す関数を指定します。例えば、グラフ作成のアプリケーションがあるとします。@<code>{y = 3x + 5} の式を @<code>{x} の値のセットに対して適用して @<code>{y} の値のセットをえるには、次のように書きます。
//emlist{
(defn y-value [x] (+ (* 3 x) 5))
(map y-value [1 2 3 4 5])
;; => (8 11 14 17 20)
//}
#@# If your function is short, you can use an anonymous function instead, either the normal or short syntax:
高階関数に渡す関数が短い場合は、無名関数を使うこともできます。無名関数には @<code>{fn} か @<code>{#} のどちらを用いても構いません。
//emlist{
(map (fn [x] (+ (* 3 x) 5)) [1 2 3 4 5])
;; => (8 1 1 1 4 1 7 2 0)