無駄と文化

実用的ブログ

スマートバンドを買って以降まんまと健康志向になっている

2023年7月19日に『ポケモンスリープ』という睡眠ゲームアプリがリリースされました。
リリース前から話題になっていて、Twitter などでもゲーム画面のスクリーンショットなどを目にするようになりました。

それを見て、
以前から睡眠のログを取りたいと思っていたこともあってスマートバンド「Xiaomi Smart Band 7」を買うことにしました。

公式サイト ( https://www.mi.com/jp/product/xiaomi-smart-band-7/ ) から引用

 

なぜ「ポケモンスリープを始めました」ではないのかというと、定期的な充電や定期的なアプリ立ち上げができない私にポケモンスリープは無理だなと思ったからです。
一方、Xiaomi Smart Band 7 なら着けっぱなして睡眠ログをとっても7日間は充電がもちます。

そんなわけでスマートバンドを左手に着けた生活が始まったわけですが...

 

まんまと運動習慣が身についてしまった

ウォーキングやエクササイズが記録され、累計時間・消費カロリー・心拍数などの数値が目に見えることによって、まんまと運動習慣が身についてしまいました。

なんやかんやで運動習慣が継続している図

Xiaomi Smart Band 7 プリインストール時点で目標設定がされています。設定した目標をクリアすると「活力にあふれています!」というメッセージが出るので、目標クリアのために毎日せっせと運動を続けてしまっています。
デフォルトの目標設定は 30分間以上の運動・500kcal以上の消費・6000歩以上の歩行 です。

自分でも驚いているんですが、8月は累計で22時間以上の運動をして10,000kcal以上を消費しています。ひと月まるまるの結果ではないのですが、それでも10,000kcalを超えられたので嬉しいです。

9月も10,000kcalを超えられるようにがんばるぞ!

 

どんな運動をしているか

ウォーキング, スクワット, ズンバ, エアロビクス などをやっています。
空き時間・外の気温・その日の気分に応じてテキトーにやっている感じです。

が、ここ最近は朝起きて勤務を始めるまえに20分間ほどズンバをやるのが習慣になっていて、健康的すぎて自分でも怖いです。

 

ウォーキングは自宅の周辺で1周8kmのコースと1周5kmのコースを決めていて、時間と相談しながらそのどちらかをグルグルしています。

スクワット, ズンバ, エアロビクス は YouTube で再生しながらまねしてやっている感じです。
下記のような動画を見ています。

ズンバ, エアロビクス を実際にやってみて良かったところは、短時間でカロリーを消費すると同時に歩数も稼げることですね。
基本的にテンポよく足踏みしながら腕を振ったり足をあげたりする動きなので。

 

食事にも気を使うようになってしまった

そんなこんなで毎日の消費カロリーをロギングして追いかけていると、そのカロリーが入ってくる部分——つまりは食事 にも気を使うようになってしまいました。
まぁせっかくなら痩せようかなという気持ちもあって。

具体的な変化は、

  • 麺類を控えるようになった
  • もち麦ごはん・雑穀ごはんに親しむようになった
  • 炭水化物の代わりに豆腐を食べるようになった
  • サラダをもりもり食べるようになった
  • サバ缶を買いだめするようになった
  • 間食を控えるようになった
  • 禁酒した

といったところです。

糖質をいっさい摂らないというような極端なことはしていません。ただただ炭水化物をドカ食いしてお腹を膨らませるのはやめました。
炭水化物の代わりに豆腐やサラダをもりもり食べています。

 

普通の豆腐もおいしく食べているのですが、「とうふそうめん風」という商品がおいしくて感動しています。

紀文オンラインショップ ( https://www.kibun-shop.com/products/tofusomen/ ) から引用

豆腐でできたそうめん風の何かというやつですが "ニセそうめん" 的な違和感は無く、付属のつゆが美味しいので普通に楽しんで食べてます。

 

サラダはスーパーに売っている350g入りの袋サラダを1日1袋のペースで買っては食べ買っては食べとしています。

こんな感じのやつ。まな板も包丁も出さずに準備が済むので袋サラダは最高。

 

さらに、「サバ缶を1日1缶食べると痩せ体質になる」というのをどっかで見たのでサバ缶を買って食べるようになりました。
サバ缶おいしい、中骨がそのまま食べられるのが良い。

 

さらにさらに、禁酒するようになりました。お酒にもまぁまぁの量のカロリーがあるって聞いたので。
本来はお酒好きなんですが晩酌は控えつつ、これからは知人友人と食事にでかけたときにしこたま飲もうと思います。

 

そんで体重はどうなったのか?

こうなりました。

うーん、まだまだですね。痩せてぇ...。

 

まとめ

そういえば、
9月中に三井の体重推移データを API として公開しようと考えているのでお楽しみに。
バックエンドを Rust で書くか Go で書くか思案中です。

 

 

私からは以上です。

オートマットのプレステージが好きだ

「オートマット」という製品がある。
プラスチックでできた板で、地面に敷き詰めることで簡易舗装ができる製品だ。

公式サイト ( https://www.web-prestige.com/automat/ ) より引用

私はこのオートマットを販売しているプレステージの公式 X (旧: Twitter) が大好きだ。

 

簡易舗装材 オートマットのプレステージ

そのアカウントがこちら。「簡易舗装材 オートマットのプレステージ」だ。
(以降、「オートマットのプレステージ」と記載)

twitter.com

この公式 X (旧: Twitter) が最高。とても良い。

オートマットのプレステージは毎日1ポストを淡々と投稿している。
投稿文は毎回固定で、1枚の画像を添える形式になっている。
文章は固定だが画像はバリエーション豊かで使い回しが少ない。オートマットの使用例をたくさん見せてくれる。

 

何が良いのか・なぜ好きか

ここから本文。

オートマットのプレステージは私にとって X (旧: Twitter) における "癒し" になっている。
投稿文に変化は無く、投稿ペースも一定。ときどき目に入って「いつもの文章」と「いろいろな画像」で楽しませてくれる。

オートマットのプレステージに "驚き" は無い。不安にさせられたり、期待を裏切られるようなことも無い。私をあわてさせるような要素はどこにも無い。
これまでも無かったし、きっとこれから先も無いだろう。

それくらい安心して見てられる。

 

まさに実家のような安心感。

 

現代のインターネットは驚き・意外性に満ちている。
センセーショナルなものほど拡散され、喜び・怒り・悲しみといった感情がひと目に晒されている。

でも、そんな "味付けの濃いインターネット" ばかり摂取していたら疲れませんか?
たまには静かな部屋でゆっくりとお茶でも飲みませんか?
「スタバの新作」ではなく「実家で出てくるいつものお茶」でこそホッと安心してくつろげる、そう思いませんか?

 

そこでオートマットのプレステージ。

 

あー、心のわだかまりがほどけてゆく。

 

投稿文を鑑賞しよう

雨が降ると地面がぬかるんで困っている方へ。ご自身で簡易舗装ができるオートマットはいかがでしょうか。
オートマット1枚のサイズは縦横50cm、厚み2cm、重さ1.8kg、耐荷重4tの硬質マットです。
オートマットは自動車バンパーのリサイクル製品です。日本製。

138文字。
コンパクトでさっぱりとした文章。でもしっかりとオートマットの良さを伝えていて爽やかな気持ちになる。

無駄がなくスッと染み込んでくる。まるで芭蕉の俳句のようだ。

 

まとめ

インターネットで疲弊しているみなさん。オートマットのプレステージをフォローしましょう。

 

 

私からは以上です。

 

蛇足

Q: これは記事広告ですか?

A: いいえ、ラブレターです

Rust における関数とメソッドの使い分け

Rust ネタです。

Rust では構造体に対してメソッドを定義できます。
公式のドキュメント では Rectangle 構造体に対して面積を求める area メソッドを定義する例が紹介されています。

struct Rectangle {
    width: f64,
    height: f64,
}

impl Rectangle {
    /// 四角形の面積を求める
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
    let rect = Rectangle { width: 3.0, height: 4.0 };
    assert_eq!(rect.area(), 12.0);
}

メソッドを定義する方法としてはシンプルで良い例なんですが、実際に自分でメソッドを書いていくと疑問が浮かんできました。
「これって普通の関数でも書けるよな?」と。

/// 四角形の面積を求める, 関数版
fn area(rect: &Rectangle) -> f64 {
    rect.width * rect.height
}

同じ処理がメソッドでも関数でも書けるとしたら、使い分けの基準は何でしょうか?一方にできて他方にできないことがあるのでしょうか?
今回はメソッドと関数の使い分けについて考えてみたことをまとめます。

 

TL;DR

  • メソッドも関数も可視性は同じ
  • メソッド呼び出しは自動借用・自動参照解決してくれるので便利
  • 多態を実現するために impl は必須
  • バイナリサイズは関数の方が小さい (?)
  • 二つのクラスにまたがるような操作は関数にしてしまう手もある

 

可視性

まず private とか protected とかのアクセス修飾子のある言語 (たとえば PHP とか) では、「private なプロパティにアクセスするためにメソッドとして定義するしかないよね」となります。

が、Rust においては可視性の取り扱い方が違うのでこの点は問題になりません。
Rust では module の 内か/外か によって可視性が制御されます。メソッドであれ関数であれ module の中からなら private なプロパティにアクセスできます。

struct Rectangle {
    // width も height も private なプロパティですが...
    width: f64,
    height: f64,
}

fn area(rect: &Rectangle) -> f64 {
    // 関数から問題なくアクセスできます
    rect.width * rect.height
}

 

自動借用・自動参照解決

メソッドとして実装するとドット演算子 . を使って rect.area() のように呼び出すことができます。
ドット演算子には自動借用・自動参照解決という便利な機能があります。

例えば

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

と定義した場合、(&rect).area() のように Rectangle の借用に対して呼び出すかと思いきや rect.area() のように呼び出せます。
これはドット演算子 . が左オペランドである rect を自動的に借用して area() を呼び出してくれるからです。

 

上記の例とは逆に、ドット演算子は参照解決も自動でやってくれます。

例えば Rectangle の参照の参照 ref_ref_rect: &&Rectangle が手元にあったとして、area() メソッドを ref_ref_rect.area() のように呼び出せます。
さきほどと同じくドット演算子 . が左オペランドである ref_ref_rect を自動的に参照解決してから area() を呼び出してくれるからです。

 

普通の関数呼び出しにはこのような機能はありませんから rect や ref_ref_rect に対して area() 関数を呼ぶときには

area(&rect);
area(*ref_ref_rect);

のようにしなければいけません。

そのためメソッドとして実装しておけば &* を気にせず雑に呼び出せて便利な気がします。
逆に、 Rust の型推論に慣れていない人は混乱のもとになるかもしれませんね。

 

多態

いわゆるポリモーフィズムというやつです。
Rust では多態を表現するのにトレイトを使います、そしてトレイトに型ごとの実装を与えるのに impl ブロックを使います。
そのため同じ名前で型ごとに異なる挙動を与えたくなったらメソッドとして実装するしかありません。

先ほどの Rectangle と area の例で云うと、area メソッド/関数が Rectangle 専用であるうちは何も問題は起きません。
Rectangle に加えて Circle や Triangle を扱い、area で面積を求めようと思うとトレイトとメソッドを持ちださざるを得なくなります。

実例として円を表現する Circle 構造体を追加で定義してみましょう。

struct Circle {
    radius: f64,
}

さらに Shape トレイトを定義します。

trait Shape {
    fn area(&self) -> f64;
}

さらにさらに Rectangle と Circle それぞれに area メソッドの実装を与えると、

impl Shape for Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

impl Shape for Circle {
    fn area(&self) -> f64 {
        self.radius * self.radius * std::f64::consts::PI
    }
}

これにて area メソッドは Rectangle に対しても Circle に対しても呼び出せるようになりました。
area をただの関数として定義した場合、このように多態にすることはできません。

 

...と云いつつ、
Rectangle, Circle が Shape トレイトを実装している前提であれば、Rectangle と Circle のいずれかを引数にとって面積を返す関数は定義可能です。

fn area<S: Shape>(shape: &S) -> f64 {
    shape.area()
}

このように。

area を多態にするために impl を使うことは避けられませんが、最終的に area 関数を実装して公開することは可能です。

 

バイナリサイズ

バイナリに差は出るのでしょうか? 実際にコンパイルしてみました。

普通の関数で実装 メソッドで実装
最適化オプション無し 9,800 byte 10,096 byte
最適化オプションあり 8,024 byte 8,344 byte

macOS Ventura 13.5, rustc 1.71.1 でコンパイルしています。
メソッドで実装したときのバイナリサイズが 3%-4% ほど大きくなりました。

うーん、これは、どうなんですかね?

 

どの構造体に属させるのか迷う時は関数にしておくのが無難

多くの言語で配列の要素を連結して文字列にするために join を使います。

例えば JavaScript では、

["A", "B", "C"].join("|");  // => "A|B|C"

例えば Python では、

"|".join(["A", "B", "C"]) # => "A|B|C"

のように書けます。

さて、JavaScript と Python の例でレシーバと引数が入れ替わっていることに気づきましたか?
JavaScript においては Array クラスが join メソッドを持っています。Python においては str クラスが join メソッドを持っています。

私は Python を学び始めた頃に "|".join(["A", "B", "C"]) という書き方にとても違和感を覚えました。
が、よくよく考えると join メソッドは

  • 文字列化可能な要素の配列を引数に取ること
  • 結果が文字列になること

から配列に属するメソッドというよりは文字列に属するメソッドと考える方が自然なんじゃないかと思えてきました。

 

が、上記のような違和感はそもそも join を関数として定義してあげれば消え去ります。
実際、Perl や PHP においては join は関数です。

join("|", ["A", "B", "C"]);  // => "A|B|C"

二つのクラスにまたがり、かつ、頻出する操作は関数になっていたほうがいいんじゃないかなと思ったりします。

 

まとめ

私なりの結論は

  • 多態を実現するために impl は避けられない
  • が、そのような場合でも同様の関数を提供することはできる
  • 二つのクラスにまたがるような操作は関数にしてしまう手もある

という感じです。

みなさまからの鉞をお待ちしています。

 

 

私からは以上です。