クロージャー(Golang and Rust)

現代の言語ではクロージャー機能を多くの言語で持っていますが、同じ機能(単純な1の加算)をGolangとRustで実装の比較。Rustの説明で出てくる、クロージャーは環境をキャプチャーできる匿名関数という定義はわかりやすい。

<Golang>

package main

import "fmt"

func add(i int) func() int {
	n := i

	clo := func() int {
		n++
		return n
	}

	return clo		// equivalent to specify anonymous function here and maybe it's more popular
}

func main() {
	a := add(1)
	for i := 1; i < 10; i++ {
		fmt.Println(a())
	}
}

<Rust>

fn f1(i: i32) -> Box<dyn FnMut -> i32> {	// FnMut recieves &mut self
	let mut i = i;						// dyn keyword sepcifies a trait pointer in the heap area
	Box::new(move || {				// force to allocate values in the heap area
		i += 1;
		i
	})
 }
 
 fn main() {
	 let mut cup = f1(0);
	 for _ in 1..10 {
		 println!("{}", cup());
	 }
 }

コードの参考は、

https://scrapbox.io/takker/Rustで関数を返す関数を作

FnMutの解説は、

https://qiita.com/hiratasa/items/c1735dc4c7c78b0b55e9

Fnでは変更できないし、FnOnceでは一度しか呼べないのでFnMutの指定になります。

比較してみると、Rustの方が細かな指定が必要ですが、これはメモリ管理に関する指定を明示的に行わなければいけない言語だからでしょう。したがってこれぐらいの例では変わらないけれども、コードは長めになります。比較してGolangは細かな操作はしなくとも使うだけなら簡単ということになるでしょうか。

Box<dyn … >については、

Boxは変数をスタック領域ではなくヒープ領域への割り当て、dynについては以下の通り、

https://doc.rust-lang.org/stable/rust-by-example/trait/dyn.html

“Rust tries to be as explicit as possible whenever it allocates memory on the heap. So if your function returns a pointer-to-trait-on-heap in this way, you need to write the return type with the dynkeyword

 

admin

 

構造体

GolangやRustでは積極的に構造体を使い、また構造体を効率的に使うための言語仕様も用意されていますが、その背景は必要なデータセットは構造体にまとめることで、読みやすく従ってバグも入りづらいコードを書くことにあるだろうと思います。

同じ機能をGolangとRustで記述してみます。

<Golang>

type Rectangle struct {
  length  float64
  breadth float64
}

func (r Rectangle) area() float64 {
  return r.length * r.breadth
}

<Rust>

struct Rectangle {
    length: f64,
    breadt: f64,
  }
impl  Rectangle{
  fn area(&self) -> f64 {
    return &self.length * &self.breadt
  }
}

Rust呼び出し方、

  fn main() {
    let mut rec = Rectangle{length:0.0,breadt:0.0};

    rec.length = 20.0;
    rec.breadt = 30.0;

    print!("{}", rec.area())
}

Golangでは

(r Rectangle)

を使って構造体と結びつけ、Rustでは

impl Rectangle

でインターフェースの如くimplementでメソッドを定義していますが、上記二種の結果は全く同じ出力をするし、記法にも大差ありません。c++ではこのような記法はないので、現代の言語の特徴と言ってもいいのではないかと思います。

 

admin

関数(メソッド)ごとに文字列と文字列スライスは意識しないといけない(@Rust)

Rustの文字型にはString(可変長)、文字列スライス(固定長)、char型(1バイト)の三種類がありますが、関数やメソッドによって引数や適用が変わってきます。

以下は文字列を全て小文字に変換する関数to_lowercase()の例ですが、操作対象は文字列スライスでなければ機能しませんし、出力はString型になります。

VScodeだと、型は自動で補完してくれますね。

fn main() {
    let text = "heLLO worLd";
    let result: String = text.to_lowercase();
    let search= "worl";

    if result.contains(search){
        println!("{} and {}", result, search);
    }

以下は関数(メソッド)のAPIの記述です、

何故、操作対象は文字列スライス型でなければならないかですが、おそらく変更がなくて参照するだけだろうからだと思います。処理量の観点でも参照の方が少なくて済むだろうし。

 

admin

 

VScodeでラズパイPico Wの環境セットアップ

Thonny、Arduino IDEで環境作ってみて、おそらく現状主要な3つの選択肢だろうと思う最後の選択肢になりますが、VScodeでPlatformIO使ってみます。

以下のリンクでPico Wも含めたセットアップ手順が記載されているのでほぼそのままです。

https://logikara.blog/raspi-pico-init/

PIO homeで新しいプロジェクトを設定して、ボードにPicoを選択後にplatformiio.iniにPico Wの設定を書き込みます。

platformio.iniファイルが変更されるとその内容に従って、必要なモジュールの読み込みが開始されてPlatformIOの領域にクローンが開始され、しばらく待つと完了。

後は通例通り、srcディレクトリのmain.cppにLチカコードを入力して、Pico Wが外部ファイルに見える状態で転送、転送完了するとPico Wが切り離されてプログラムが動作開始します。実は外部ファイルモードにしていなくとも、VScodeが外部ファイルモードにしてUSBシリアルでファイル転送をして、再度外部ファイルモードを終了するという一連の操作を自動で行なってくれるのでこれは便利です。

特にArduino言語で差し障りなければ、VScode + PlatformIOが一番素直であるように思います。

 

admin

ラズパイPico WのWi-Fi接続機能

MicroPythonのサンプルあったのでそのままですがMicroPythonでつないでみた。

構成はラズパイPico Wの既存のWi-Fiに接続、同じネットワークのブラウザから制御というArduinoやM5Stackなどと同じ方法です、APモードにも出来るでしょうが。

http://usicolog.nomaki.jp/engineering/raspberryPi/raspberryPi_picoW.html

のコードそのまま、ただしWi-FiのSSID/PWは自分用に設定必要です。

Thonnyのコンソールメッセージ、自分に割り当てられてIPアドレスを表示しています。

指定の通りブラウザから呼び出すと、ブラウザの画面はこんな感じ。

ON/OFF指定でオンボードLEDの状態が切り替わります。

 

admin

 

ラズパイPico WのRust

ラズパイPico WのLチカが動かないなと思って、専用のファームがあるのかとも思ったけど、そんな理屈はない。MicroPythonはインタプリタだから実行環境必要だけど、Rustは実行ファイルになっているからそのまま実行出来るはず。

で実はHALがPicoとは別物(embassy)で、オンボードのLEDは無線モジュールから出力されている。MycroPythonやArduino IDEではPico/Pico Wのハードの違いを開発環境側で吸収しているんだろう。

この辺の記述は以下のリンクが参考になります。

https://qiita.com/Azi/items/422c654bb476e0abf118

LEDブリンクのソースコードは、

https://github.com/embassy-rs/embassy/blob/main/examples/rp/src/bin/wifi_blinky.rs

になります。Pico W用のHALは今現在も活発にアップデートされているので、安定的に使えるようになるのは今少し時間が必要です。それまではMycroPython/Arduino IDE/VS code環境で使うのが良さそうです。

 

admin

ラズパイpicoのデバッグ方法

USBインターフェースを本来の目的に使ってしまうと、USB経由のシリアルデバッグはできなくなるので、C/C++に限定されますが以下のやり方がありそうです。

① もう一枚picoを用意してデバッガーにする、ただし接続の取り回しに苦労しそう

② スイッチサイエンスで販売されているデバッグプローブを使う、論理的には搭載CPUも同じだからほぼ互換だろうと思う

https://www.switch-science.com/products/8708

恐らくこちらの方が使いやすい。接続インターフェースはSWDと言われる2ピンのインターフェース(GND必要だから実質3ピン)が、下の右センター付近にシールドで引き出されているからここに接続すれば良いはず。

SWDというのはJTAGが4ピン使うので小型のターゲットでは使いずらいのでARMが独自に設定した独自のプロトコルだそうです。バウンダリースキャンはできずに単純にデータの書き込みと読み出しに限定された機能です。

デバッグプローブ(picoprobe)ができることは、

https://github.com/raspberrypi/picoprobe

使い方は、

https://datasheets.raspberrypi.com/pico/getting-started-with-pico.pdf

セットアップしようとしましたが、Javaが必要と言われてJavaをインストールしても見つからない?と言われる。

 

admin

syntax sugarはなぜsugarなのか?

今更ながらですが、wikipediaでは以下のように説明されています。

つまりまわりくどい表現を人間にとって分かりやすい(より心地よい : sweeter)表現に置き換えてくれるからと読めば良いようですから、それは説明として分かりやすいと思いました。

 

admin

ラズパイPico W(Thonnyで)

ラズパイpicoを動かす環境には、

・Arduino IDE(Arduino言語)

・VScodeにPlatformIO(C言語)

gccを使うので、Arduino/M5StackのようなPlatformIOとの組み合わせでは無いですね。

https://qiita.com/n0bisuke/items/f4ff96bd74932c8def77

・Thonny(MicroPython)

が有力どころですが、以下を参考にThonny(4.1.2)、MacBook Airで動かしてみます。

https://krr910183393.wordpress.com/2021/02/15/raspberry-pi-pico-micropython-thonny-python-ide/

Thonnyのインストールは完了している前提で、

① シリアルポートを選択します

Thonnyの右下でインタプリタをインストールして、ファイルから切り離された状態で以下のように見えるはずなのでシリアルポートでラズパイpicoを選択する。シェル画面端のように接続状態になります。

Note : この時にはUSBシリアルで見えていなければならないので外部ファイルモードでは選択できません。Thonnyでは外部ファイルモードを使うのはMicroPythonのUF2ファイルを書き込むときだけです。

このように接続されています。

② サンプルコードを入力します(PICO本体搭載LEDの0.5秒毎ブリンク)

③ 緑矢印をクリックすると起動、停止させるには赤stopアイコンをクリック

ただしこの状態ではpicoにテンポラリーに保存されているだけのようなので、電源オンで自動起動させるためには次のステップが必要

④ 電源オンで自動起動させるには、『ファイル』『名前をつけて保存』でRaspberry Pi Picoにmain.pyの名前で保存すれば自動起動

ただしパソコンのUSB経由でファイルに見えている状態では、そちらが優先されます。コードの書き換え考えたら妥当な仕様ですが。

P.S. (2023/9/5)

Thonny(MicroPython)の実行環境からArduino IDEを使ってしまうと、再度Thonnyを使うときには再度MicroPythonの実行環境をインストールしないといけません。

 

admin

ラズパイPico W(Arduino IDEで)

タイトル通りですが、picoをArduino IDEで使ってみました。

参考は以下のサイトですが、微妙にUIは異なるので想像力を駆使してセットアップ。

https://logikara.blog/raspi-pico-arduinoide/#mokuji_4

ポイントはボード追加とシリアルポートの設定だろうと思います。ボードはリンクの通りのURLから設定すれば良くて、シリアルポートの設定はUF2 Boardを選択します。

白ボタン押しUSBコネクタ挿入で外部ファイルと認識できれば、サンプルプログラムをシリアルで送信、送信完了すると切り離されてプログラムが自動スタートします。

 

Thonnyでうまく点灯しなかったLEDの動作が確認できました。

 

admin