Closed21

型安全にbashを書けるAmberを試す

きむそんきむそん

前提

M3Mac で試している

$ uname -m
arm64

$ sw_vers
ProductName:		macOS
ProductVersion:		14.2.1
BuildVersion:		23C71
きむそんきむそん

環境構築

公式ドキュメントだと以下のスクリプトで入るらしい

curl -s "https://raw.githubusercontent.com/Ph0enixKM/AmberNative/master/setup/install.sh" | bash

ただ brew にも一応あるっぽく可能な限り brew で管理された状態で入れたいので brew から入れてみる(なにか問題があれば公式Docの方でやり直す)

$ brew install amber
きむそんきむそん
$ curl -s "https://raw.githubusercontent.com/Ph0enixKM/AmberNative/master/setup/install.sh" | bash

$ amber --help
Amber's compiler
Version 1.0.0

USAGE:				EXAMPLE:
For evaluation:
	amber [INPUT]		amber foo.ab
	amber -e [EXPR]		amber -e "\$echo Hello World\$"
For compiling:
	amber [INPUT] [OUTPUT]	amber foo.ab bar.sh

🤟

きむそんきむそん

基本を抑える

きむそんきむそん

拡張子は .ab らしい

でトランスパイルすると bash スクリプトが書き出される(TS -> JS の関係)

let fruits = ["Apple", "Banana", "Orange"]

loop fruit in fruits {
    echo "Fruit: {fruit}"
}

を用意して

$ amber ./sample.ab sample.sh

すると

__AMBER_ARRAY_0=("Apple" "Banana" "Orange");
__0_fruits=("${__AMBER_ARRAY_0[@]}");
for fruit in "${__0_fruits[@]}"
do
    echo "Fruit: ${fruit}"
done

が書き出される

きむそんきむそん

型チェックについては CLI でトランスパイルするときに怒ってくれる感じみたい

let fruits = ["Apple", "Banana", "Orange"]

loop fruit in fruits {
    let x = fruit * 10
    echo "Fruit: {fruit}"
}

文字列への掛け算を書いてトランスパイルさせようとしてみると

$ amber ./sample.ab sample.sh
 ERROR 
Multiply operation can only multiply numbers
at ./sample.ab:4:19


3| loop fruit in fruits {
4|     let x = fruit * 10
5|     echo "Fruit: {fruit}"

こんな感じで怒られる。エラーがわかりやすい

VSCode 拡張機能は入れたけど保存してもエラーは表示されていないのでおそらく CLI で型エラーが出るだけっぽい。ここは今後に期待したい

きむそんきむそん

コマンドは $内容$ を使って実行する

トランスパイル前
$mv ./a ./b$ failed {
  echo "It seems that the file.txt does not exist"
}
トランスパイル後
mv ./a ./b
__AMBER_STATUS=$?;
if [ $__AMBER_STATUS != 0 ]; then
    echo "It seems that the file.txt does not exist"
fi
きむそんきむそん

関数を試す

fun add(arg1: Num, arg2: Num): Num {
    return arg1 + arg2
}

echo "1 + 2 = {add(1, 2)}"

シグネチャに型がかける

型チェックも同じくCLIでのみエラーが表示される

➜ amber ./sample.ab sample.sh
 ERROR 
Expected expression
at ./sample.ab:5:20


4| 
5| echo "1 + 2 = {add('hello', 2)}"
6|
きむそんきむそん

https://docs.amber-lang.com/basic_syntax/importing
一応ファイルインポートができるらしい。main block もあるので

fun add(arg1: Num, arg2: Num): Num {
    return arg1 + arg2
}

if __name__ == '__main__':
    echo "1 + 2 = {add(1, 2)}"

みたいな形で書いて直接呼ばれたときはechoを実行するし、importされたときは関数だけ提供するもできるっぽい

きむそんきむそん

おまじない: set -e との相性が悪い

$set -euxo pipefail$ failed {
    echo "Failed to set"
}

$mv ./test.txt ./test2.txt$ failed {
    echo "Failed to move"
}

吐き出されるコードは set -e を考慮しないのでこれを実行すると

$ amber ./sample.ab
+ __AMBER_STATUS=0
+ '[' 0 '!=' 0 ']'
+ mv ./test.txt ./test2.txt
mv: cannot stat './test.txt': No such file or directory

amber で failed に書いた処理が実行されない

なので、set -e した上で

unsafe $set -euxo pipefail$
unsafe $mv ./test.txt ./test2.txt$
echo "next line"

みたいに unsafe で書いていくか、amber 的には failed を強制させてはくれるので

$mv ./test.txt ./test2.txt$ failed {
    echo "Failed to move"
    unsafe $exit 1$
}

echo "next line"

のように明示的に失敗したときの処理で exit してあげる形になりそう。amber 的にはたぶん後者なのかな。

きむそんきむそん

型エラーがリアルタイムに見たい

せめて watch オプションで見れないかなと思ったけど

$ amber --help
Amber's compiler
Version 1.0.0

USAGE:                          EXAMPLE:
For evaluation:
        amber [INPUT]           amber foo.ab
        amber -e [EXPR]         amber -e "\$echo Hello World\$"
For compiling:
        amber [INPUT] [OUTPUT]  amber foo.ab bar.sh

本当に最低限でそのまま実行する or トランスパイル(+型チェック)が逐次実行でできるだけって感じ。npm-watch とかと組み合わせれば一応できそうだけど設定の手間がかかって大変

きむそんきむそん

使えそうなケース

Altbash、ちょっといいなと思ったんだけど実際 bash スクリプトを置きたいのってインストールなしで実行させたいみたいなモチベーションから来てるのでそうなると使い所に悩むなーという感想だった。
インストール必要なら別に @ts-check + zx とか、あるいは bun, deno +zxで良いし。

.ab ファイルと .sh ファイルの両方をコミットすれば

  • ファイルを編集するなら amber CLI が必要(開発環境)
  • 実際に実行するときには sh を実行すれば良い(amber をインストールをしたくない特定の環境)

みたいな形にはできるので、便利スクリプトを書くみたいな用途ならこの形になるのかなー。

きむそんきむそん

あとは OSS とかでシェルスクリプト自体とかインストールスクリプトを配布している場合とかは結構良さそう。.ab ファイルだけをコミット対象にして一定秩序ある状態でシェルスクリプトを書きつつ、書き出されたファイルのみを配布すれば良い。

きむそんきむそん

という感じで

  • シェルスクリプト自体をライブラリやツールとして配布したい場合に一番マッチしそう
  • リポジトリの便利スクリプトとして書くシェルスクリプトのために使うのはややアンマッチ感を感じる
    • 使うなら .ab.sh の両方をコミットしておき、編集するには amber CLI が必要だが、実行だけなら依存なしで実行できるよ、みたいな形になりそう
    • 現状の開発体験とデータ構造的には不便なので、シェルスクリプト自体が成果物にならないなら zx + 任意のランタイム(node.js + ts-check or bun or deno, ...etc)のが better かなという感想
    • node 以外のエコシステム下なら良いかもしれない
きむそんきむそん

まとめ

  • Amber はちょうど TypeScript のように .ab.shにトランスパイルしてくれるくん
    • 静的な型チェックが行える
  • CLI や VSCode Extension はまだあまり機能が充実しておらず、実行前に静的に検査できる安全性が得られるくらいがメリットで開発体験にはあまり寄与しない(補完や開発中の型エラー表示は期待できない)
  • シェルスクリプト自体を配布したい場合には(一定の学習コストはあるものの)結構良さそう。比較的秩序ある書き方ができる
  • 便利スクリプトみたいな枠としては、連想配列がなかったりまだ拡張機能だったりが充実していないのもあって、学習コストを抜いても言語やTS(or JS + JSDoc の型チェック) + zx のほうが良いなーという感想だった
きむそんきむそん

結構用途が限られるなという感想だったけど、まだ Alpha なので今後改善するかもしれない

このスクラップは5ヶ月前にクローズされました