思索的逍遥の記。

いろいろな考え事。

Pythonista 3 で Google 翻訳を使いやすく (1) UI を設定する

モチベーション

Pythonista 3 は高機能な iOS 向け Python 開発環境。

Pythonista 3

Pythonista 3

  • omz:software
  • 仕事効率化
  • ¥1,220

しかし、ダウンロードしたはいいものの、使い方や使い道がいまいちピンと来ていなかった。

そこで、他の方がこれまでどんなものを作ってきたのか調べてみた。

なるほど、便利そう。

プログラミングに関する情報をググるとき、少なからず海外サイトを巡ることになるので、アプリの切り替えの手間が省けるのはとても助かる(ただ、複数アプリを画面に並べられる iPad では、普通にブラウザと Google 翻訳アプリを並べるだろう)。

まずは上の記事を参考に、ほぼ同じものを作ってみたが、次の点で欲が出始めた。

  • 画面を上下分割すると、ソフトウェアキーボードが出た時に下半分が完全に見えなくなる(コピペのために上下を行ったり来たりしたい時に不便)
  • リンクの貼り付け・移動にも対応したい
  • どうせなら、ブラウザの共有メニューから Python スクリプトを起動したい

これらを踏まえて、自分なりにプログラムに改善を加えてみた。コード全体はこちら(スクロールで全体が見られます)。

The script for switching two WebViews on Pythonist ...

スクリプトの使用イメージ

完成品の使用イメージはこんな感じ。

Image from Gyazo

ブラウザの共有メニューから iOS のショートカットアプリを経由して、Pythonista に URL を渡しつつ起動する。これをどう実現したのかを解説していきたい。今回は UI の構築方法に焦点を当てる。

.pyui ファイルに UI 設定を入れる

Gist のコードでわかるように、.pyui ファイルは json 形式になっているが、Pythonista のアプリ上では専用のエディタが起動するので、項目ごとに入力して行くと良いだろう( json の key / value が編集画面の項目 / 設定値に対応している)。

全体的なレイアウトは次のような感じ。上の+ボタンで各ウィジェットを追加でき、ドラッグで大まかな位置に配置する。位置や大きさの微調整は i ボタンで表示される入力画面で数値入力することで行える。

WebView が webview2 の1つしかないように見えるが、webview1 がこの裏にあり、ボタン(SegmentedControl、ここでは「サイトビュー | Google翻訳」という表示)で最前面に出る WebView を切り替えている。次の編集画面を見れば、2つの WebView が同じ座標にあるのがわかる。

webview1

webview2

これで、ソフトウェアキーボードに画面下半分が隠れる問題は解消された。また、リンクを表示・編集するためのテキストフィールド、WebView の履歴を進めたり戻ったりするためのボタンも追加している。

これら以外にもいろいろなウィジェットが存在する。詳しくは Pythonista 公式のドキュメントを参照。

ここまで準備できたら、見栄えは完成である。このあとは、この .pyui ファイル を Python スクリプトで呼び出し、各ウィジェットに関数を紐付けていく。記事が長くなったので、その解説は次回にしようと思う。

怠惰は悪ではない

 怠惰であることは悪いこととされている。しかし忙しない現代人は、今一度、怠惰の効用を見直すべきではないだろうか。

 というのも、インターネットが普及している今、人間が晒されている情報の波は以前よりも圧倒的に高い。また、インターネット上の情報は整理されているようで、実は体系的でないものであふれている。そのような環境にあって、脳にかかる負荷は意識しているよりもかなり大きなものとなっているように思える。

 であればこそ、休みは重要である。何もしないぐうたらが今こそ重要である。現代人は、休みと称してネットサーフィンしたり動画漁りをしたりSNSで活動したりと、むしろ忙しくしている。それはそこに容易に手に入れられる快感があるからだが、容易とは言え忙しいには違いない。無意識に、自分の休息の時間を縮小してしまっているのだ。

 マインドフルネスだとか、デフォルトモードネットワークだとかを取り上げるまでもなく、暇でぼんやりするしかない時間を、現代人は意図的に作り出すべきだ。社会生活に追われている時こそ、真に自分が自由となる時間を創出するべきだ。今過ごしている環境にある楽しみは、必ずしも自分の味方とはならない。楽しみの味は甘いがゆえ、つい食べ過ぎてしまい、脳の生活習慣病となるだろう。断食とまでは言わないが、快感の裏に密かな疲労を感じたら、実はやめどきかもしれない。続きを後でできるものなら、一度取り置くのが良いだろう。

 怠惰と聞いて思い浮かぶのは「めんどくさ」という感覚である。この「めんどくさ」さを感じた時に休めば良いのではないか、とも考えたが、しかしこの「めんどくさ」は、必要な時に機能するとは限らない。人間が「めんどくさ」と思う物事の基準は、その物事にかかる工程の数ではない。工程の数と、その工程によって得られる快感の総量のバランスである。しかし、疲れは快感によって帳消しにはならない。快感は人を騙すだけである。騙されることが悪いというわけではない。騙されればこそ、人はある作業について「苦労を払ってもよい」と思えるものだ。その見返りに見合った苦労なら、喜んでしよう。しかし快感はときに必要以上に人を騙すことがあることも、覚えておきたい。その場合、必要以上に疲労するだろうから。また一方で、必要でないときに「めんどくさ」さを感じることがあるのも、お忘れなく。これらは総じて、認知の歪みによって生じる現象である。

 快感が「コスト支払い」のインターフェースであるとすれば、怠惰は「コスト未払い」のインターフェースである。怠惰を有効に活用すれば、余計な快感への余計な出費を抑えられる。契約関係により仕事を遂行したり楽しみを享受したりする義務があるのでなければ、現代人はより積極的に怠惰になった方が良いのではないか。その方が、自分が本当に楽しみたいと思った対象を、より存分に楽しめるだろう。細かいことにとらわれないで、自分の本当に大切にしたいものを見極めることが、積極的な怠惰への第一歩かもしれない。

後記

 長い間ブログを更新せずにいたが、実は精神的にかなり疲労してしまい、療養のような期間を過ごしていた。自分の理想のために、自分を無意識に縛り過ぎていたために起こったことだ。その理想も今考えればどこか幻想にとらわれていたような内容である。折を見てこのことについて振り返っていきたいと思うが、まずはもう少し脳の休養を続けたい。この記事自体、自分の反省を織り込んでいるところがある。だいぶ調子が戻ってきたとは思うので、このようにリハビリのような文章を起こしつつ、もう少し静観していきたいと思う。

Rustでライフゲームを作ってみた

モチベーション

ニコニコ動画で面白いプログラミング動画を見つけましたが、その動画で C で実装されていたライフゲームを Rust で書き直すと練習になりそうだったので、ちょっと書いてみました。ちょうど ncurses の rust 向け wrapper があったので良かったです。

免責事項: 筆者は趣味でプログラミングをしている者なので、間違いが含まれている可能性があります。ご注意ください。

元ネタの動画様

業界のネタも散りばめられていて楽しめます。自分は業界人ではありませんが、プログラミングを勉強しているとついつい目にしてしまう情報の数々……。

ソースコード

所詮初心者が書いたコードなので、Rust っぽくなかったり、至らないところがあると思います。ご容赦ください。

Cargo.toml

[package]
name = "life_game-rs"
version = "0.1.0"
authors = ["SuitCase <foo@example.bar>"]

[dependencies]
ncurses = "5.0"

main.rs

2018/09/07 更新:条件分岐をいくつか match に置き換えました

extern crate ncurses;

use ncurses::*;
use std::char::from_u32;

const W: usize = 80;
const H: usize = 20;

fn show(buf: [[i32; W]; H]) {
    for y in 0..H {
        mv(y as i32, 0);
        for x in 0..W {
            match buf[y][x] {
                0 => { addch(' ' as u32); },
                _ => { addch('*' as u32); },
            }
        }
    }
}

fn wrap(x: i32, bound: usize) -> i32 {
    let mut ret_x = x;
    while ret_x < 0 {
        ret_x += bound as i32;
    }
    while ret_x >= bound as i32 {
        ret_x -= bound as i32;
    }
    ret_x
}

fn step(buf: &mut [[[i32; W]; H]; 2], cur_buf: usize) {
    for y in 0..H {
        for x in 0..W {
            let mut neighbors = 0;
            for dy in -1..2 {
                for dx in -1..2 {
                    if dy == 0 && dx == 0 {
                        continue;
                    }
                    let ny: usize = wrap(y as i32 + dy, H) as usize;
                    let nx: usize = wrap(x as i32 + dx, W) as usize;
                    if buf[cur_buf][ny][nx] != 0 {
                        neighbors += 1;
                    }
                }
            }
            match buf[cur_buf][y][x] {
                0 => { buf[cur_buf^1][y][x] = (neighbors == 3) as i32; },
                _ => { buf[cur_buf^1][y][x] = (neighbors == 2 || neighbors == 3) as i32; },
            }
        }
    }
}

fn main() {
    let mut buf = [[[0; W]; H]; 2];
    let mut cur_buf = 0;
    initscr();
    noecho();

    let mut cursor_y: usize = 0;
    let mut cursor_x: usize = 0;

    loop {
        show(buf[cur_buf]);
        refresh();
        mv(cursor_y as i32, cursor_x as i32);

        let ch: char = from_u32(getch() as u32).expect("Invalid char");

        match ch {
            'q' => { break; }
            'h' => { cursor_x -= 1; }
            'l' => { cursor_x += 1; }
            'j' => { cursor_y += 1; }
            'k' => { cursor_y -= 1; }
            's' => { buf[cur_buf][cursor_y][cursor_x] = 1; }
            'c' => { buf[cur_buf][cursor_y][cursor_x] = 0; }
            'n' => { step(&mut buf, cur_buf); cur_buf ^= 1; }
             _  => { continue; }
        }
        cursor_x = wrap(cursor_x as i32, W) as usize;
        cursor_y = wrap(cursor_y as i32, H) as usize;
    }
    endwin();
}

感想

前に C++ を勉強して挫折しました。Python でプログラミングに慣れた後に、またコンパイラ型言語を勉強しようと思って、一方で「また C++ はモチベが上がらない。何か新しい言語で代替物は……」という気持ちもあって、登場時にちょっと気になってた Rust を勉強することにしました。

Rust も書いてみると気をつけることは多くて、結構躓きます。このプログラムでは以下の点で立ち止まってちょっと考えました。

  • C言語ではif文の条件に int 型を使って良いが、Rustでは bool 型にしなければならない。
  • 配列のインデックスは usize 型にしようね、とコンパイラに言われたので、扱う数値型が i32 になったり usize になったりした。
  • ncurses の getch 関数の戻り値が u32 だとコンパイラに教えられた( ncurses-rs のドキュメントがない……)。
  • 今回のプログラム中の step 関数は、元ネタ様では引数に inbuf, outbuf( buf 配列内の2つの配列)を指定していたが、Rust でそれをやると、inbuf と outbuf を表現するのに cur_buf(元ネタ様では current_buf )を2回使うことになり、Rust コンパイラ「2回借用してるんだけど」と怒られたので、buf を丸ごとと、cur_buf を関数に直に渡して、関数内で2つの buf を表現することで回避した。C で悩まなくてもいいところで悩むポイントの1つだなと実感した。

しかし、今回 Rust プログラムを書いてみて、ちゃんと動いて楽しかったのも事実です( match がとても気持ちいい)。もっと練習を積み重ねて、作りたいツールを作れるようになったらなあ……と感じた次第です。

意欲の湧かないタスクに対して

繰り返す過ちへ、如何にアプローチするか?

事あるごとに反省を繰り返している。同じ失敗を何度も重ね、その度に工夫しようと思うのに、結局実行できないか、考えるのを諦めてしまう。しかし、失敗の原因はいつも同じもののように思うので、それらにフォーカスすると、何か見えてくるかもしれない。

この記事の時点では、まだ問題は解決していない。とりあえず、現時点での分析を覚書程度にここに記しておき、時間を置いて再度この投稿への反省を記事にしてみたいと思う。

過ちの具体的な姿を見極めてみる

大雑把に言えば、時間管理に関係する問題である。やるべきことは決まっているのに、それを遂行する気力が起きない。そして気がつくと、やるべきことが終わらないまま、期限間近となってしまう。そしてやるべきことが終わっていないか、中途半端な出来となってしまうために、期限が来ると失敗が確定してしまう。失敗する案件は多くの場合、自分で自ら課した課題ではなく、他人から要請された目標に対してのタスクである。

失敗する要因として考えられるもの

失敗へと至る道筋の中で、悪さを働いている(様に見える)原因を、思いつく限り挙げてみる。

  1. そもそも自分が能動的にやろうとしているタスクではないため、取り掛かるためのモチベーションがなく、上げるのも難しい。
  2. 他にやりたいことがあり、そちらのモチベーションが上回っているため、作業が脱線してしまう。
  3. 疲労や眠気など、生物学的な限界が立ちはだかっている。

以下では、今挙げた問題について細かく考察していきたい。

やりたくない、興味のないタスクに向き合うために

ある行動を起こしたいという欲求は、生物学的には学習によって増強されたり、抑制されたりする。この現象に関わるシステムは複雑であろうが、今はその様に単純に考えよう。 上記の考え方に従うと、あるタスクについて意欲が湧かないということは、その時点までにそのタスクに関係する事象を経験した時に(あるいは現在進行形で)、肯定的な情動的評価がなされていない、ということが考えられる。そのタスクに対して、肯定的でない情動を抱くに至る要因はなんだろうか? 以下に考えられるものを挙げてみよう。

  • その事象に対して、嫌悪感を覚えたことがある。
  • その事象に対して、自分が興味を持つものに比較して、より弱い印象しか持たなかった。
  • その事象に全く興味がないわけではないが、向き合うための物理的・精神的余裕がない。

これらについて考えていく。まず、その事象に対して嫌悪感を覚えているなら、一人で事態を打開することは難しい。この場合、他人にその嫌悪感の存在を打ち明け、遂行を手伝ってもらうしかない。また、おそらくその事象にあまり印象を持っていない時も、同じことが言えるだろう。一人でなんとかできる可能性のあるものは、3つ目の、その事象に向き合うだけの余裕がないパターンだけかもしれない。

余裕がない、という状況は、シンプルに言えば「他の事象によって邪魔されている」ということに尽きる。他の事象に、なぜ邪魔されうるのだろう。それは、その時自分が、その他の事象にコントロールを奪われているからである。例えば同時並行で、何かに対する執着や悩みを感じており、その感情を処理する作業に忙殺されれば、必然的に他のタスクには向き合えなくなる。また、期限まで余裕がない場合、時間がないことへの焦りばかりを感じて、無計画に、無節操にタスクに取り組んでしまえば、上手くいかずに投げ出すことだってあるだろう。そうした、気づきづらい自分の膠着した感情を明らかにして、解決してからタスクに取り掛からなければ、上手くいかない状態はいつまでも解決しない。

厄介なのは、自分がより興味を持つものに対する執着、という原因がありうるということである。自己肯定感・自己効力感が乏しいとき、それを満たすために、自分が得意なものに打ち込むだろう。得意なものの方が、少ない努力でより良い結果を残せるので、取り組みやすいのである。そして、その得意なことに対しても自分が能力上の不満を抱いているなら、よりその対象へ没頭してしまうだろう。他のことがダメならなおさらである。要するに、自分の最も興味関心のある対象、自分のホームグラウンドが、自分自身の存在意義を存続させるための最後の砦なのである。この様になってしまった場合、自分の精神状態の良悪の変化は、その自分の興味の対象にコントロールを掌握されてしまう。自分が心の拠り所に思っている対象への思いが強ければ強いほど、この問題は顕著になってしまい、解決は難しくなる。

解決策として考えられるのはまず、決してその執着を無碍にせず、自分が何に対して執着を抱いているのかをできるだけ詳細に理解するところから始めることである。そして、その執着の手綱を時折、一時的に緩めることができるように、意図的に訓練していく。執着を緩めることができれば、その時、何か心が軽くなった様に感じる反面、執着し続けたものへの愛着を一時的に封印することへの寂しさを感じることだろう。完全に執着を捨ててしまう、という手もある。しかし、その執着を捨ててはならないものだと感じる場合、無理に捨ててはならない。捨てるなら、ある程度自分で悩んで納得してからである。緩めた手綱をまた打ち振るったり、また緩めたりすることでモードチェンジできる様になれば理想的である。ただしそれを覚えすぎても、ダブルスタンダードになった時にまた別の精神的問題が噴出しかねないので、その執着の対象と、現在心を向けるべきタスクの両立に整合性があるかどうかも、考慮する必要があるかもしれない。

ただし、上記の様に考えすぎても疲れる一方なので、考えるならしっかり休養をとって、頭を空っぽにしてからである。そして、タスクが多ければ多いほど考えることも増えるので、後回しにできるタスクを、取り組むべき適切なタイミングまで考えてから、一度放置しておくことを覚えたい。そうすることで、適切な休養も取れる様になるだろう。一方で、執着している対象をあまりにも放置しすぎると、執着の度合いが返って増して、問題がさらに悪化するかもしれない。それに対しては、他のタスクでの成功をより確実にする工夫をすることと、執着の対象に向き合う時間を確保することを同時並行で行っていくことで、自己効力感を温存し、問題を和らげることができるかもしれない。

本記事のまとめ

結局、自分が何に対してどれくらい工夫し頑張るのか、エネルギーの振り分けを考えるのが大事だと、今のところ考えている。自分の中の一定時間あたりのエネルギーは有限である。しかし長い目でみれば、生活していく中でエネルギーは外部から供給され続ける。だから考えなしにエネルギーを浪費し続けるのではなく、長期に渡って安定的にエネルギーを燃やして行くことを考えれば、成せることも増えていくことだろう。

冒頭に記したように、自分の場合まだ問題は解決していない。だからこの考察は終わりではない。今後、この考察をより改善していければと思う。

最初の記事。

SuitCaseと申します。テストも兼ねた初投稿。

1. なぜブログを始めたのか

ただの日記だったら一人で勝手に書いて保存していれば良い。 つまり、ブログを始めたということは、誰かに文章を見てもらいたいということだ。 正確に言えば、「誰かが読める状態で文章を公開しておきたい」ということかもしれない。 普段から、書きたいことがあれば日記を書いてきた。そしてその中には誰かと共有したい内容も含まれていた。 しかし余程の機会がなければ、普段の生活でそれについて誰かと話をするということはないだろう。 そうして、その内容は自らの手元に死蔵される。

ネットには匿名性があり、それがゆえに自らが感じる責任は軽くなり、言論を気兼ねなく公開しやすい。 これには、気づかぬうちに他者を傷つける可能性があるという罠が潜んでいるから、最低限それは注意して投稿したい。 とにかく、ブログであれば、自分の言論を、その原型に近い形で表現できるだろうと考えた。 つまらないものから本気に思っていることまで、自分の語りたいがままの文章を、ここに綴っていきたい。

2. 何を、どんな風に書くのか

いまだに、自分が何を書くかということについては定まっていない。 自分の専門は生命科学だと思うが、おそらく分量的にその話題は少なくなると思う。 内容はおそらく、音楽、アニメ、映画、小説、プログラミング……などの趣味や、ざっくり人生についてなどの分類不能な考え事。 趣味に関しては所詮素人の文章になるので、誰かに読んでいただける際には、間違いなどに対してはお手柔らかにご指摘願いたい。 また、ここまでいささか高圧的な物言いになってしまっていて、申し訳なくも思うが、つまるところストレス発散のために始めた側面もあるので、その点についてはご容赦願いたいと思う。目に余る失礼を働いてしまった場合はご指摘願いたい。 そもそも、読まれても読まれなくてもいいという気持ちで書いていくので、目を通して頂いて、何かを思っていただけるだけで御の字である。記事の更新は不定期になるだろうが、最低でも月に一度の更新を目指したい。

それでは、拙文だが以上を挨拶に代えさせていただき、最初の記事を締めさせていただく。それでは。