はじめに
JavaプログラマがCurlを習得する際、最も大きなハードルと感じるのは言語仕様そのものでしょう。そこで今回は、CurlとJavaとの構文等の比較を行います。
1 変数宣言と利用頻度の高いデータ型
まずは、変数の型や宣言方法などよく利用する構文から説明します。
1-1 基本的な型
次の表を見て分かるように、プリミティブ型とStringの型名は、JavaとCurlでは大差ありません。
Java | Curl | Curl(符号なし整数) |
---|---|---|
int | int | uint |
byte | byte/int8 | uint8 |
short | int16 | uint16 |
long | int64 | uint64 |
char | char | |
float | float | |
double | double | |
boolean | bool | |
void | void | |
String | String | |
Date/Calendar | DateTime |
Curlは、符号なし整数を扱うこともできます。その場合はuintやuint8を使用します。また、IntegerやDoubleといったラッパークラスに相当するクラスはCurlにはありません。
1-2 変数宣言
Curlで変数を宣言するには「let」を使用します。letで始まる文を「let ステートメント」と呼びます。
String str = "abc";
let str:String = "abc"
「any」を使用して型定義なしに変数を宣言することも可能です。この場合の型は、動的に決定されます。
let value:any
1-3 null値を許容する変数宣言
Curlでは、null値を許容する変数であることを指定して宣言することが可能です。null値を許容する場合、型の前に#を記述します。
let str:#String = null
次のように、nullを許容しない変数に対しnullを代入すると、エラーになります。
let str:String = null
今回の記事のソースは次のコードを変更することで試すことができます。テキストエディタなどで編集し、ブラウザにドラッグするだけで、Curlアプレットを実行できます。
{curl 6.0 applet} {curl-file-attributes character-encoding = "shift-jis"} {value let str:String = "abc" || この行を変更する str || 値が表示される }
1-4 代入
Curlで代入を行うには、「set」を使用します。
str = "xyz";
set str = "xyz"
1-5 final
変更不可能な値を宣言するには、定数修飾子「constant」を使用します。
final String abc = "abc";
let constant abc:String = "abc"
1-6 インスタンス生成
Javaと同じく、Curlでインスタンスの生成を行うには「new」を使用します。
Person person = new Person();
let person:Person = {Person}
コンストラクタに変数をセットして生成する場合は、次のようになります。
Person person = new Person("Mike", 22);
let person:Person = {Person "Mike", 22}
1-7 配列、List
int[] array = new int[4];
int[] array = {1, 2, 3, 4}
List<Integer> array = new ListArray<Integer>(); array.add(1); array.add(2); array.add(3); array.add(4);
Curlで配列の定義を行うには、「FastArray-of」もしくは「Array-of」を使用します。
FastArray-of は Array-of よりも高速ですが、最大容量はその作成時点で固定され、利用できるメソッドのセットもそれほど多くはありません。
let array:{FastArray-of int} = {{FastArray-of int} max-size = 4}
let array:{FastArray-of int} = {{FastArray-of int} max-size = 4, 1, 2, 3, 4}
let array:{Array-of int} = {{Array-of int} 1, 2, 3, 4}
let array:{Array-of int} = {Array-of int} array.append(1) array.append(2) array.append(3) array.append(4)
1-8 Map
CurlでMapに値を挿入する際は「set」を使います。値を取得する際には「get」を使うか、直接キーを指定して取得します。
Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); map.put("b", 2); map.put("c", 3); int aVal = map.get("a"); int cVal = map.get("c");
let map:{HashTable-of String, int} = {new {HashTable-of String, int}} map.set "a", 1 map.set "b", 2 set map["c"] = 3 let a:int = {map.get "a"} let c:int = map["c"]
1-9 コメント
単一行コメントには、「||」を使用します。また、「|#」から「#|」までがコメントとして扱われます。
// コメント
|| コメント
/* コメント1 コメント2 */
|# コメント1 コメント2 #|
2 演算子
演算子もいくつか異なるものがありますが、プリミティブ型と同様にJavaと類似しています。
演算子 | Java | Curl |
---|---|---|
足し算 | + | + |
引き算 | - | - |
掛け算 | * | * |
割り算 | / | / |
剰余 | % | mod |
値の増 | i++; | {inc i} |
値の減 | i--; | {dec i} |
AND | && | and |
OR | || | or |
NOT | ! | not |
文字列連結 | + | & |
同等 | == | == |
不等 | != | != |
小なり | < | < |
大なり | > | > |
以上 | <= | <= |
以下 | >= | >= |
3 制御文(if/for/switch/while/例外処理)
次は、条件分岐やループなどを行う制御文の比較を行います。
3-1 if文
条件処理を行うには、Javaと同様に「if」を使用しますが、条件式の後ろに「then」を記述する必要があります。「else」についてもJavaと同様です。
この辺りからCurl独自のカッコの記述に慣れが必要になってきます。
if文
if(条件) { .... }
{if (条件) then .... }
if-else文
if(条件) { .... } else { .... }
{if (条件) then .... else .... }
if-else if-else文
if(条件1) { .... } else if(条件2) { .... } else { .... }
{if (条件1) then .... elseif (条件2) then .... else .... }
Curlで条件を複数記述するとき
次のように()内に条件を書き、「and」などでつなぎます。
{if ((foo < bar) and (bar == baz)) then .... }
3-2 switch文
Curlのswitch文では、「switch」「case~do」「else」を使用します。
switch (値) { case 要素1: ... break; case 要素2: ... break; default : ... break; }
{switch 値 case 要素1 do ... case 要素2 do ... else ... }
3-3 for文
回数指定やインデックスを使用してループを行う場合には、「for~to~do~」を使用します。
for (int i=0; i < 10; i++) { ... }
{for i:int=0 to 10 do ... }
また、Javaの拡張for文に対応するループもあり、「{for~in~do~」という構文になります。
for (int val : listOfInt) { ... }
4 パッケージ/クラス/メソッド
次は、独自にクラスなどを作成するときに必要になる構文を主に説明します。
4-1 パッケージ宣言
package宣言を行うには、「package」を使用します。
package com.samples; ...
{package com.samples ... }
4-2 import
importを行うには、「import~from~」を使用します。
import jp.codezine.*; import jp.codezine.Foo;
{import * from jp.codezine;} {import Foo from jp.codezine;}
4-3 アクセスレベル
Curlのアクセス修飾子は、下記表の対応するJavaの修飾子と同じ意味になります。例えば、protectedなら、サブクラスと同じパッケージのクラスからアクセス可能です。
Java | Curl |
---|---|
public | public |
protected | protected |
パッケージプライベート(未指定) | package |
private | private |
4-4 クラス定義
クラス定義を行うには、「define-class」を使用します。
public class Monkey { ... }
{define-class public Monkey ... }
4-5 メソッド定義
メソッド定義を行うには、「method」を使用します。
public class Dog { public String call() { return "Bow Wow!"; } }
{define-class public Dog {method public {call}:String {return "Bow Wow!"} } }
また次のようなコードでメソッドをコールできます。
{curl 6.0 applet} {curl-file-attributes character-encoding = "shift-jis"} {define-class public Dog {method public {call}:String {return "Bow Wow!"} } } {value let dog:Dog = {Dog} let result:String = {dog.call} result }
引数がある場合は、メソッド名の次に引数を指定し、メソッドをコールするときはメソッド名の後ろに引数を記述します。
{method public {methodName arg0:int,arg1:String}:void ... }
{obj.methodName 99, "foo"}
Javaと同様に、可変長引数もサポートされています。
また、Curlには、コンパイラがメソッドの呼び出しを実際のメソッドのコードに置換するということを指定する「inline」というメソッドの修飾子などもあります。さらに、戻り値については、void、1個の戻り値以外に複数の戻り値を返すことも可能です。詳細は次のURLを参照にしてください。
4-6 抽象クラス定義
Javaと同様に「abstract」を使用します。
public abstract class Animal { ... }
{define-class public abstract Animal ... }
4-7 継承
継承を行うには、「inheritsブロック」の中にSuperクラスを記述します。
public class Monkey extends Animal { ... }
{define-class public Monkey {inherits Animal} ... }
Curlではインターフェースを作れない代わりに多重継承が可能となっています。また、Javaと同様にメソッドのオーバーライドも可能です。
{define-class public Foo {inherits Bar,Baz} ... }
4-8 instanceof
Javaのinstanceofに相当する演算子は、「isa」です。
if(value instanceof Person) { ... }
{if (value isa Person) then ... }
4-9 キャスト
Monkey monkey = (Monkey)object;
Monkey monkey = Monkey.class.cast(object);
キャストを行うには、「asa」を使用します。
{let monkey:Monkey = object asa Monkey}
5 Javaに存在しないCurlの仕組み
Curlの仕組みの中にはJavaには存在しないものも多くあります。前述の中では、4-5.メソッド定義で機能を紹介した「メソッドが複数の戻り値を返すことができる仕組み」などが挙げられます。その中で、特徴的な仕組みを挙げて説明をします。
5-1 数量・単位
Curlは型の他に単位も持っています。例えば、距離を表すDistance型には、meterや、inchという単位があります。異なる単位での数値計算や比較も可能です。
{let d:Distance} {set d = 1meter + 50inch}
また、Velocity型はDistanceをTimeで割った型だという独自の定義も可能です。科学計算を行う場合には、プログラミング言語にCurlを利用するのも良いのではないでしょうか。
Curlがサポートしている単位は「距離」「質量」「時間」の他に「角度」「光度」「相対距離」などもサポートされています。詳細は次のURLを参照してください。
5-2 プロシージャ
JavaScriptなどで利用されるクロージャ機能もあります。Curlでは「匿名プロシージャ」とも呼ばれます。プロシージャとして型定義を指定するために、「proc-type」と「proc」を利用します。
ここでは、単純な足し算のクロージャを例にとって説明します。
{value let p:{proc-type {int, int}:int} = {proc {arg1:int, arg2:int}:int {return arg1 + arg2} } let result:int = {p 10, 20} result }
まず、クロージャを作成するには、「procマクロ」を利用します。procマクロの引数に、実際に必要な引数(ここで足し算する2つの値arg1とarg2)を"{"と"}"で囲み、その後戻り値の型を「:」の後に記載します。
このクロージャ自体を変数に代入する場合(上記の例では、pという変数に代入)、上記のように「proc-typeマクロ」を利用しプロシージャ変数の型を定義します。このプロシージャを実行するには、上記のように{プロシージャ変数 引数1, 引数2}のように記述します。
また、この変数をさらに他のプロシージャやメソッドの引数として指定できますので、JavaScriptでよく利用されるコールバック関数的な使い方もできます。
まとめ
JavaとCurlの構文を比較すると、予想以上に似ている箇所があったのではないでしょうか。また、Curl独自の強力な機能もあります。Curlを始めた場合、Curl独自の括弧の記述に慣れ、今回紹介した構文を利用できるようになるまでが最初のステップではないかと思います。
今回で、本連載は最終回になります。本連載が、Curlを使用する開発者のリファレンスとして少しでもお役に立てれば幸いです。これまでご愛読いただいた読者の皆さまありがとうございました。また株式会社カールの方々には毎回レビューをして頂きました。この場を借りて改めてお礼申し上げます。ありがとうございました。