※v8.0からサポートされます。
データ型として Decimal 型が使用できるようになりました。
Decimal は符号と scale プロパティを伴った96ビットの仮数部を使用して浮動小数点数を表すことができます。
正の 79,228,162,514,264,337,593,543,950,335 から
負の 79,228,162,514,264,337,593,543,950,335 まで
の範囲の10進数を表し、多数の有効な整数桁と小数桁をサポートします。
ソース
{curl 8.0 applet} {curl-file-attributes character-encoding = “utf8”} {import * from CURL.LANGUAGE.MATH} {let vb:VBox = {VBox {HBox “max-value is:”,Decimal.max-value}, {HBox “min-value is:”,Decimal.min-value} } } {value vb }
|
実行結果
サンプル
http://developers.curlap.com/curl/v8/decimal.curl
{Curly Bracket}
式とは基本的にCurl言語のコマンドを指します。Curlではほとんどの式が{と}で囲まれるようになります。そもそもCurlの名前の由来は、この”{“(Curly Bracket)からきています。式の中に式を記載する場合は、さらに{と}で囲むこととなります。そのため、式を囲むブラケットの数でコードのレベルを示すこととなります。
{define-proc {my-proc}:void {message-box “ABC”} }
{my-proc}
|
value式
value式は、複数のコードを記載し、最後の部分式の値を結果として画面や変数へ返します。
{value let v = 1 || この式は{let v = 1}と記載することも可能です。 set v = 2 || この式は{set v = 2}と記載することも可能です。 v }
|
実行結果
2
do式
do式は、valueと似ていますが、doは結果を返しません。
{do let v = 1 || この式は{let v = 1}と記載することも可能です。 set v = 2 || この式は{set v = 2}と記載することも可能です。 }
|
実行結果
結果なし
コメント
Curlでの1行コメントは、||を利用します。複数行のコメントには|#と#|で囲みます。
{do let v = 1 || 1行のみコメント |# 複数行コメント #| }
|
宣言と代入
Curlでの値の宣言方法は以下のように「let 変数名:データ型 = 初期値」となります。
let str:String = “あいうえお” || もしくは{let str:String = “あいうえお”}
|
以下のように複数の変数を同時に宣言することもできます。
let (str:String, int:i) = (“あいうえお”, 123)
|
値を代入する場合は、下記のようにsetを使います。
set str = “ABCDE” || もしくは{set str = “ABCDE”}
|
let同様に、以下のように複数の値を同時にセットできます。
set (str, i) = (“かきくけこ”, 456)
|
この際にJava等の言語と違い、注意しないといけないことはNullを許容しないということです。もしNullを許容する変数を宣言する場合は、「#データ型」というような形式でシャープを付与して宣言する必要があります。
Curl6.0からサポートされた宣言方法で、定数を宣言する場合は、defという宣言の仕方ができます。これは定数としての宣言となります。また、データ型をしているする必要もありません。
def str = “あいうえお” || let constant str:String = “あいうえお”と同様
|
式の結果を代入
式の結果を代入することができます。例えば、ifやswitch、valueの結果を変数に代入することができます。以下はif文の例です。
set str = {if a > 1 then “あいうえお” else “かきくけこ” }
|
値の増減
Javaのi++やi–のように値の増減をコーディングするには、incやdecを利用します。
関連ドキュメント
基本構文
条件式について説明していきます。
if文
基本的なルールは以下のようになります。
{if 式 then … elseif 式 then … else … } |
サンプルは以下のようになります。
let x:int = 1 let y:int = 2 {if x > y then {output “xが大きい”} || outputは出力コンソールに表示するものです。 else {output “yが大きい”} } |
ちなみに、Curlの特徴的な利用方法で、if文は値を返しますため、以下のように利用できます。
let x:int = 1 let y:int = 2 {output {if x > y then “xが大きい” || outputは出力コンソールに表示するものです。 else “yが大きい” } }
|
unless文
これはif文の逆ですね。基本的にはあまり使わないと思います。
switch文
他の言語でもサポートされているswitch文です。値の評価には数値だけでなく、どんなデータ型でも可能です。
{switch 比較変数 case 値1 do … case 値2 do … else … } |
サンプルは以下の通りです。
let x:int = 1 {switch x case 0 do {output “xは0”} case 1, 2 do {output “xは1か2です”} else {output “xは3以上の値”} }
|
type-switch文
データ型別に処理を行いたいときはtype-switch文を利用します。基本的にはswitch文と似ていますのでサンプルのみ下に記載します。
{type-switch x case i:int do {output “xはint”} case f:float do {output “xはfloat”} else {output “xはintでもfloatでもないです。”} }
|
関連ドキュメント
条件式の構成
Curlでのループ式の利用方法です。Curlでは、for、until、whileを利用することができます。また、他言語同様break、continueも装備しております。
for文
for文にはいくつかの記述方法があります。まずは、範囲内でのループの記述方法を記載します。
例えば、1づつ増加させていくようなループ文を記載するには、{for … to … step … do …}もしくは{for … below step … do …}を利用します。この2つのfor文は似ていますが、toは~までで、belowは~以下という場合に利用します。具体的なサンプルは以下の通りです。
|| 1づつ増やしていく {for i:int = 0 below 8 do {output i} } |
これは0から7までの値をコンソールに表示します。またstepは、増分する値の幅を指定するために利用できます。
|| 2づつ増やしていく {for i:int = 0 below 8 step 2 do {output i} }
|
また減らしていく場合は、donwtoもしくはaboveを利用します。
|| 2づつ減らしていく {for i:int = 8 above 0 step 2 do {output i} }
|
コンテナループについてはコレクション・クラスを説明の機会に紹介します。
while文
次にwhile文の記述方法です。条件がtrueの間、処理を繰り返します。
サンプルは以下のようになります。
{while start < 10 do {output start} set start = start + 1 } |
until文
Curlではuntil文についてもサポートしております。これは条件がfalseの間、処理を繰り返します。
サンプルは以下のようになります。
{until start == 10 do {output start} set start = start + 1 } |
breakとcontinue
Curlは、他言語同様、breakやcontinueについてもサポートしております。
関連ドキュメント
ループ式の構成
クロージャ
Javascriptなどで利用されるクロージャ機能はCurlにもあります。これは匿名プロシージャとも呼ばれます。これにはprocマクロを利用します。また、プロシージャとして型定義を指定するために、proc-typeマクロが用意されています。この機能を具体例に沿って説明していきたいとおもいます。
{curl 6.0 applet}
{value let p:{proc-type {int, int}:int} = {proc {a:int, b:int}:int || 足し算の結果を返す {return a + b} }
{output {p 10, 20}} || 30 {output {p 5, 30}} || 35 }
|
ここでは、単純な足し算のクロージャを例にとって説明します。まず、クロージャを作成するには、procマクロを利用します。procマクロの引数に、実際に必要な引数(ここで足し算する2つの値aとb)を”{“と”}”で囲み、その後戻り値を”:”の後に記載します。あとは、中身のロジックを記載していきます。(ここでは足し算をし、結果を返すというものです。)また、このクロージャ自体を変数に代入する場合(上記の例では、pという変数に代入)、変数の型を定義するため、上記のようにproc-typeマクロを利用します。
このプロシージャを実行するには、変数名を”{“と”}”で囲み、実行します。例えば、上記のように{p 引数, 引数}のようにいます。また、この変数をさらに他のプロシージャやメソッドの引数として指定できますので、Javascriptでよく利用されるコールバック関数的な使い方もできます。
グローバル・プロシージャ(関数)
Curlでは、グローバルな関数(プロシージャ)も作成することができます。具体例を以下に記載します。
{curl 6.0 applet}
{define-proc public {add a:int, b:int}:int || 足し算の結果を返す {return a + b} }
{value {output {add 20, 30}} }
|
これを作成するには、define-procマクロを利用します。あとは、メソッドを作成するようのと同様に記載し、利用いたします。(もちろんpublic以外のプロシージャも作成できます。)
ラムダ式
C#でもサポートされているラムダ式がCurlでも利用できます。これによりプロシージャを利用する際、コード量を減らすことができます。サンプルは以下のようになります。
|| 通常のプロシージャ def x = {proc {i1:int, i2:int}:int {return i1 * i2} }
|| ラムダ式(fnというマクロ。C#と同様=>演算子を利用します。 def x = {fn i1, i2 => i1 * i2}
|
関連ドキュメント
匿名プロシージャと引数
Curlにはキーワード引数と残余引数という独特な引数を付与できます。
通常の引数
プロシージャやメソッド等の通常の引数では以下のようにします。
|| プロシージャの作成 {define-proc public {my-proc1 i:int}:void || 処理 }
{my-proc1 100} || 実行
|
キーワード引数(Keyword Argument)
Curlの持つキーワード引数とは、「引数 = 引数のデフォルト値」というように、プロシージャやメソッド等にセットします。以下に例を記載します。
|| プロシージャの作成 {define-proc public {my-proc2 i:int = 100}:void || 処理 }
{my-proc2 i = 200} {my-proc2} || {my-proc2 i = 100}と同等 |
また、複数キーワード引数を指定することや通常の引数と混合させることができます。
|| プロシージャの作成 {define-proc public {my-proc3 str:String, i:int = 100, f:float = 1.0 }:void || 処理 }
{my-proc3 “abc”, i = 200} {my-proc3 “efg”, f = 2.0} {my-proc3 “xyz”} {my-proc3 “abc”, i = 200, f = 2.0}
|
キーワード引数の利点としては、キーワード引数の値をセットする必要がなければ省略できますし、順番が前後しても特に問題がありません。
残余引数(Rest Argument)
残余引数とは、引数に名前(変数)を持たない引数を、無制限に受け取ることができます。これは3つのピリオド”…”として指定します。また、”…:String”のように、型を指定することができます。
{define-proc public {my-proc4 …}:void }
{define-proc public {my-proc5 i:int, …:String}:void } |
プロシージャの中では以下のようにコンテナループでそれぞれの引数を順に取得することができます。
{define-proc public {my-proc6 …}:void {for v in … do {output v} } }
{my-proc6 “abc”, “def”, 123, 1.0, true} |
ちなみに残余引数の数を算出するにはcount-argumentsマクロを利用します。例えば、{count-arguments …}のようになります。
詳細については、こちらを参照ください。
クラス
Curlでクラスを作成するにはdefine-classを使用します。
{define-class public Person || ここにコンストラクタ、メンバ、メソッド等をコーディング } |
クラスのインスタンス化は、以下のようにします。
let p:Person = {Person} もしくは let p:Person = {new Person}
|
コンストラクタ
コンストラクタは、constructorを利用します。また、デフォルトコンストラクタはdefaultという名前で作成します。
{define-class public Person
field private _name:String
{constructor public {default name:String } set self._name = name } }
|
default以外のコンストラクタも複数作成することができます。
{define-class public Person
field private _name:String
{constructor public {default name:String } set self._name = name }
{constructor public {TestConstructor first-name:String, last-name:String } set self._name = first-name & ” ” & last-name } }
{let p1:Person = {Person “amori”}} || デフォルトコンストラクタ {let p2:Person = {Person.TestConstructor “akira”, “mori”}} || コンストラクタTestConstructor
|
フィールド、ゲッター(getter)、セッター(setter)
フィールドは上記の例の中の_name:Stringのように記載します。
また、ゲッター、セッターをCurlでは定義できます。Java等ではgetName、setNameのような名前でメソッドとして定義するのが通常ですが、Curlではゲッター、セッターをsetter、getterを利用して、定義することができます。
{define-class public Person
field private _name:String
{getter public {name}:String {return self._name} }
{setter public {name _name:String}:void set self._name = _name }
{constructor public {default name:String } set self._name = name } }
{let p:Person = {Person “amori”}} {output p.name} || ゲッター {set p.name = “hokada”} || セッター
|
また、getter、setterを簡単に記述するために、以下のサンプルのように、フィールドにアクセサとして記述することができます。
field public-get private-set x:String field public-get package-set y:int field public-get z:bool |
メソッド
メソッドの定義には、methodを利用します。
{define-class public Person
field private _name:String
{constructor public {default name:String } set self._name = name }
|| 戻り値 : Stringのメソッド {method public {toString}:String {return {format “I’m %s.”, self._name}} } }
|
クラスの継承
クラスを継承するには、inheritsを利用します。また、construct-superを利用して、親クラスのコンストラクタをコールすることができます。さらに親クラスのメソッド等をコールするには、superを利用します。
{define-class public Member {inherits Person} || 親クラス
field _id:int
{getter public {id}:int {return self._id} }
{constructor public {default id:int, name:String } {construct-super name} } }
{let m:Member = {Member 1, “amori”}} {output m.id} {output m.name} || 親クラスのゲッター
|
また、Curlでは多重継承もサポートしております。多重継承をするには、inheritsの中に複数のクラスをカンマ区切りでコーディングします。
{define-class public Child {inherits Oya1, Oya2, Oya3} || 親クラス(多重継承)
|| ……. }
|
抽象クラス(abstract)
CurlではJavaのようなインターフェースはサポートされていません。ただし、抽象クラスを作成することはできます。(もちろんabstractなメソッド)これを利用するには、修飾子にabstractを指定します。
{define-class public abstract AbstractPerson
{method public abstract {toString}:String } }
|
アクセス属性
Curlのアクセス属性は、public、private、package、protectedを指定できます。それぞれの説明は以下のとおりです。
public |
全コードがメソッドを呼び出すことができることを示します |
package |
同じパッケージ内のコードのみがメソッドを呼び出すことができることを示します(デフォルト) |
protected |
同じパッケージ内のコードまたはサブクラス内のコードのみがメソッドを呼び出すことができることを示します |
private |
同じクラス内のコードのみがメソッドを呼び出すことができることを示します |
アクセス属性「library」
バージョン7からlibrary属性を付与できるようになりました。これは同じマニフェスト内ではpublicのような動きをし、違うマニフェストからはpublicとしてアクセスできないというものです。これにより、ライブラリなどで内部的にはパッケージ間で利用したいが、外部公開したくない場合にやくにたちます。(これはJava7のmoduleのような機能)
詳細は、こちらを参照ください。
Curlではファクトリパターンを“ファクトリ”という機能を利用して、簡単に実装できます。これはfactoryを利用します。
|| TestFactory {define-class public abstract TestFactory
{getter public abstract {name}:String }
{factory public {default switch:int = 1 }:TestFactory {return {if switch == 1 then {Class01} || 子クラスのインスタンス生成 else {Class02} || 子クラスのインスタンス生成 } } } }
|| Class01 {define-class public Class01 {inherits TestFactory} {getter public {name}:String {return “class 01”} } }
|| Class02 {define-class public Class02 {inherits TestFactory} {getter public {name}:String {return “class 02”} } }
{do def fac = {TestFactory switch = 2} {output fac.name} || 実行結果はClass02.nameの”class 02” }
|
ファクトリの詳細はこちらをご覧ください。
パッケージの作成
Curlでパッケージを作成するには、まず以下のようにヘラルドにpackageを指定します。そのファイル内にpackage式を利用し、パッケージの内容を記述します。
{curl 6.0 package}
{package COM.CURLAP.ABC, author = “amori”, copyright = “Copyright ….”, version = “1.0” }
|| ここに、クラスやプロシージャ等を定義していく。 |
ちなみに、Javaのようにディレクトリをパッケージ名と合わせる必要はありません。また、いくつかのファイルから構成される場合も、このpackageを指定しているファイル内で、includeを利用してファイルを読み込むことができます。
{curl 6.0 package}
{package COM.CURLAP.ABC, author = “amori”, copyright = “Copyright ….”, version = “1.0” }
|| クラス等を定義した外部ファイルを読み込む {include “abc1.scurl”} {include “abc2.scurl”}
|| 直接クラス等を記載できる。 {define-class public A || … } {define-class public B || … }
|
パッケージのインポート
パッケージをインポートするにはimportを利用します。
{import * from COM.CURLAP.ABC, location = “load.scurl” || 例えば上記のファイル名がload.scurlの場合 } |
スーパーパッケージ
java7で出てきたsuperpackageのようなことも可能です。例えば以下のようにスーパーパッケージ(ここではCOM.CURLAP.SUPERPACK)を作成し、そのパッケージに含めるサブパッケージ(ここではCOM.CURLAP.AとCOM.CURLAP.B)をpublic属性付きでimportします。
{curl 6.0 package}
{package COM.CURLAP.SUPERPACK}
{import public * from COM.CURLAP.A} {import public * from COM.CURLAP.B}
|
これをアプリケーションで利用する場合には、{import * from COM.CURLAP.SUPERPACK}と記述しますと、COM.CURLAP.AもCOM.CURLAP.Bもimportできます。
詳細については、こちらを参照ください。
Curlは、以下のような多くのデータ型をサポートしています。
プリミティブ型(整数、浮動小数点数、ブール値、文字、数量)
整数
小数部を持たない数値です。
int、int8、int16、int32、int64、uint、uint8、uint16、uint32、uint64、byte
浮動小数点
小数部を持つ数値です。
float、double
ブール値
trueまたはfalseのいずれかを格納します。デフォルトはfalseです。
bool
文字
文字(Curl言語の文字はUnicode標準に準拠しています。)
char
数量
数量は、値とそれに関する測定単位が一体となったものです。
Acceleration、Angle、Area、Distance、EmDistance、Fraction、Frequency、Intensity、Mass、Percent、PixelDistance、Resolution、Speed、Time
クラス型
これはdefine-classで作成されるクラスです。文字列、コレクションなどの組み込むクラスも含まれます。
プロシージャ
プロシージャをproc-typeマクロを利用し、変数の型として定義できます。詳細はプロシージャとクロージャを参照ください。
列挙型
指定した要素の固定リストから成るデータ型です。これはdefine-enumで定義することができます。
any型
任意のデータ型を格納できます。プリミティブを含むこともできます。デフォルトはnullです。変数に格納される値のデータ型がわかっている場合は、anyは利用しないでください。
各データ型の詳細は、こちらをご覧ください。
CurlにもJava等同様に以下のように例外をtry~catchできます。
{try || 処理 catch 例外1 do || 例外1発生時の処理 catch 例外2 do || 例外2発生時の処理 finally || finally処理
}
|
また例外クラスを作成するには、以下のサンプルのように、Exceptionクラスを継承して作成します。
{define-class public MyException {inherits Exception} {constructor public {default message:String} {construct-super message} } }
|
このような例外を発生させるには、throwマクロを利用します。
{throw {MyException “My exception has occurred.”}}
|
以下はサンプルです。
{try let i:int = 0 {if i < 0 then {throw {MyException “exception!!”} } catch e:MyException do {popup-message e.message} } |