The AWK~plus Programming Language
AWK~plus
The AWK~plus Programming Language は、
- プログラム言語AWK (The AWK Programming Language) 仕様と GNU
GAWK の主要な拡張機能の実装
- 型推論と 関数型プログラミングによるシンプルな外観
- 言語レベルでの ロックフリーでスレッドセーフな並列プログラミングのサポート
- 動的型付 (インタプリタ) と 静的型付け (コンパイラ) をハイブリッドでサポートする型システム
などの特徴を持つ
次世代スクリプト実行環境です。 |
|
- プログラム言語AWK (The AWK Programming Language) 言語仕様を実装
- GNU GAWK の主要な拡張機能をサポート
Note:
プログラム言語AWKの例題をそのまま実行可能であり、実行結果は GNU GAWK とバイナリレベルで一致する。
(コンパイラは一部、非互換あり)
Note:
正規表現、printf フォーマット変換などは
Java仕様を採用しており `awk4j' の方が GNU GAWK との互換性は高い。
- Java クラスの利用
- メソドの動的呼び出し、ダックタイピング (Duck typing)
- インターフェイスの動的実装 (Implements)
- イン
ターフェイスの動的ミック
スイン合成 (Mixin composition)
関数値は他の関数と同じように呼び出せる関数オブジェクトで、 apply メソドが呼び出されたときに実行される。
関数値 = '.' 関数呼び出し ;
function add(a, b) { return a
+ b }
function calc(x: Function)
{ return x.apply
} # 関数値呼び出し
print calc(.add(1, 2))
# 3
ダックタイピング (Duck typing)
関数値を使用して クラスの継承関係を無視した メソッド呼び出しが 安全に実行できる。
if (duck is bird.Duck)
duck.quacks()
# duckがクラス bird.Duckのインスタンスなら
quacksを呼び出す
if (.quacks()
in duck) duck.quacks() # インスタンス
duckにメソド quacksが存在すれば quacksを呼び出す
Note: duck typing
In Computer Programming, duck typing is a style of dynamic typing in
which an object's current
set of methods and properties determines the valid semantics, rather
than its inheritance from a particular class.
The name of the concept refers to the duck test,
attributed to James Whitcomb Riley, which may be phrased as follows:
If it walks like a duck and quacks like a duck, I would call it a duck.
リスナーの実装 (Listener)
関数値を指定して、リスナーを生成できる。 (sample/ImageViewer6.awk
参照)
val baseurl = ARGV[1]
val imageLabel = new javax.swing.JLabel("",
javax.swing.SwingConstants.CENTER)
val frame = new javax.swing.JFrame("AWK~Plus - ImageViewer")
BEGIN {
val DELAY_SECONDS = 60
val FRAME_HEIGHT = 320
val FRAME_WIDTH = 240
frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE)
val dim = frame.getToolkit().getScreenSize
frame.setLocation(new java.awt.Point(dim.width-7 -
FRAME_WIDTH, dim.height-55 - FRAME_HEIGHT))
val container = frame.getContentPane
container.add(imageLabel)
val adapter = new
plus.awt.Mouse(.mousePressed(null))
# ヘルパ関数 Mouseで関数値をラッピング
container.addMouseListener(adapter)
actionPerformed(null)
frame.pack
frame.setVisible(true)
val actionListener: java.awt.event.ActionListener = # リスナーインターフェイスの動的実装
plus.reflect.Reflection.implement("java.awt.event.ActionListener", .actionPerformed(null))
new javax.swing.Timer(1000 * DELAY_SECONDS,
actionListener).start
}
function mousePressed(e:
java.awt.event.MouseEvent) {
if (1 != e.getButton)
frame.setAlwaysOnTop(!frame.isAlwaysOnTop)
}
function actionPerformed(actionEvent:
AnyRef) {
imageLabel.setIcon(new javax.swing.ImageIcon(baseurl
strftime("/HHmm") ".jpg"))
}
スレッドの生成 (Concurrent)
関数値を指定して スレッドを生成できる。
(sample/C2.awk 参照)
var counter: Int = 0
var sum: Int = 0
function atomCount()(n:
Int) {
while (10000 >= (n = ++counter)) sum += n # スレッドセーフな共有変数の更新
}
val T[1] = Future(.atomCount())
# スレッドを生成、これはクロージャ(Closure)
val T[2] = Future(.atomCount)
# 引数が空の場合は'()'を省略可能
Join(T); assert(50005000 == sum) #
スレッドの終了を待ち合わせる
Note:
クロージャ(Closure) は自由変数を保持した関数オブジェクトで、
見えている変数に対して閉じているためにクロージャと呼ばれる。
Note:
言語レベルで並列プログラミングをサポートしているため、
ロックフリーでスレッドセーフな変数の更新が可能。
Note: Future など拡張された組み込み関数については
lib/predef.awk を参照するとよい。
変数の型変換は以下のとおり。
"" X #
文字列に変換
X -0 # 数値タイプに変換
int(X) #
組み込み関数を使用してプリミティブ数値に変換 (他に double,float,long)
val x: タイプ = X # X
のタイプはコンパイラが認識している必要がある (Objectタイプは不可)
val y: タイプ = 連想配列.cast(キー) #
連想配列から強制キャストして読み出す
コマンドラインオプション (Options)
- -F fs
--field-separator fs
- 組み込み変数 FS に fs を設定する
- -v var=val
--assign var=val
- スクリプトが実行される前に変数 var に値 val を設定する。
変数の値は BEGIN ルールの中でも使用可能
実行パラメータ (Parameters)
実行パラメータは ARGV 変数に代入される。
ファイル名の変わりに
var=val 形式のパラメータを指定した場合は、 ストリーム参照時にグローバル変数 var へ val を設定する。
インタープリタは AWK~plus
言語仕様の全てをサポートする 動的型付けモードで動作するため AWK言語仕様との互換性が高い。
java plus.Plus ソースファイル名
[[コマンドラインオプション]
実行パラメータ ]
コンパイラは、 型推論による静的型付けモードで動作する。
# Compile
java plus.Plus -d 出力ディレクトリ ソースファイル名
# Run
java クラス名 [[コマンドラインオプション] 実行パラメータ ]
Note: -d は クラス出力ディレクトリ指定
Note: スクリプトのコードはプラットフォーム依存であるが
改行は win と unix 形式のどちらでもよい。
Android は utf-8 のため、
コード変換が必要なら
nkf (漢字コード変換フィルタ) がおすすめ。
制限事項
- 関数仮パラメータは val 属性であり変更は不可
(*
function
f(a) { a = 0 } *)
- 配列要素への代入は オブジェクトを返すため、
連続代入をおこなう場合は 先頭に記述する
(* var a = B[0] = c = 0 *)
サンプルの実行は以下のとおり。
make sample
エラトステネスのふるい (Eratosthenes) による、
四則演算、文字列結合、連想配列アクセスを多用
した場合の実行結果を以下に示す。
(想定範囲の結果になっている (^^;)
make era
« Windows-XP, Java7 »
言語 |
実行時間(秒) |
相対値 |
Java |
0.23 |
1 |
Kotlin |
0.24 |
1 |
Xtend |
0.34 |
1 |
plus (Kotlin Compiler) |
0.86 |
4 |
Scala |
1.00 |
4 |
GNU AWK 4.0.1 |
1.xx |
4 |
plus (Scala Compiler) |
1.34 |
6 |
Groovy |
2.39 |
10 |
Jython (Python) |
3.66 |
16 |
plus (Interpreter) |
8.84 |
38 |
plus
(Interpreter) |
27.80 |
121 |
« Ubuntu 12.04 »
言語 |
実行時間(秒) |
相対値 |
Java |
0.31 |
1 |
Kotlin |
0.34 |
1 |
Scala |
1.08 |
3 |
plus (Kotlin Compiler) |
1.24 |
4 |
plus (Scala Compiler) |
1.80 |
6 |
GNU AWK 3.1.8 |
1.xx |
3 |
plus (Interpreter) |
8.03 |
26 |
plus
(Interpreter) |
27.80 |
121 |
Note: Winと Linuxの振る舞いの差は、
Java VM (client | server) の違いが大。
Note:
GNU AWK の実行時間は 秒単位。
動作環境は以下のとおりで、別途 Java実行環境 (JRE) を用意すればよい。
Note: Win環境で make が必要なら GNU
Make for Windows または mingw-and-ndk
などからダウンロードすればよい。
Note: Scala ライブラリは
軽量化のため必要なもののみ組み込んでいる。
Scala の全機能が必要な場合は、 Scalaをダウンロードして パスを通せばよい。