巷で大人気のPythonには豊富なライブラリ群があります。
教材の類も充実してますし、会社や研究室の先行プロジェクト資産もあるでしょう。
Hylangは幸いにしてPythonとの連携機能が充実しているので
こういった先行資産を活用しながら、徐々にLisp色に染めていくというスタイルを
現実的に実行可能なヤベぇ特徴を備えています。
今回はオープンソースなロボットアームOpen Manipulator Xを
シリアル通信経由で操作する単純なアプリケーションを考えます。
実際のところ
当該ロボットアームはUbuntu端末からシリアル通信経由で所定の指令文を送ることで操作します。
Pythonでやると、こんな感じになります。
import serial ser = serial.Serial('/dev/ttyACM0', 57600) ser.write("task,up\n")
これをHylangで書き直してみましょう。
ライブラリのインポート
まず、ライブラリインポートですが、これはそのまんま。
(import serial)
変数設定
次に変数設定。
letは残念ながらない*1ので、
Hy公式のスタイルに則ってsetvで値を定義します。
文字列はダブルクオートじゃないと受け取って貰えないので注意!
(setv ser ( serial.Serial "/dev/ttyACM0" 57600))
シリアルの書き込み
次に書き込みです。なんも考えないと、こんな感じの実装になるかと思います。
(ser.write (str.encode "task,back\n"))
Clojure由来らしい魔界記法"スレッドマクロ"をつかうと……以下のように書き下せます。
(-> (str.encode "task,up\n") (ser.write) )
指令文本体は単体の要素として先に切り出して渡してあげてもいいので……
(-> "task,up\n" (str.encode) (ser.write) )
この例ですと旨味がないですが、"."記法を使う場合、
スレッドテイル・マクロを使い末尾にくっつけるようにして
こう書くこともできますね。
(->> "task,down\n" (.encode str) (.write ser) )
書き込み部を関数に切り分ける
スレッドテイル方式のものを関数に切り分けましょう。
defunじゃなくてdefnです。
(defn robotTask [dist] (-> (+ "task," dist "\n") (str.encode) (ser.write))) (robotTask "up")
繰り返し処理も見通しよくなりますね。
(import time) (for [x ["right" "down" "left"]] (robotTask x) (.sleep time 6.0))
*1:欲しい時は自分で作りましょう