Programmer's Note

コード読み書きの備忘録。

XcodeでMGIsDeviceOneOfType is not supported on this platform.

iPhoneアプリ開発入門しようと、アップルのチュートリアルに従いなら、アプリを作ってったのだが、 コードを追加したあとエミュレータを実行すると、XCodeがエラーを吐いて止まってしまう。

  MGIsDeviceOneOfType is not supported on this platform.

スタックトレースが表示される。ネットで調べると 解決方法は、XCodeを古いバージョンに戻すか、OS含めた最新バージョンにするしかないようだ。

一回 Xcode を 9 に戻したが、自分のiPhone SEiOS 12に対応してなかった・・・・。 仕方なくMac OS AirのOSを10.13から10.14にアップグレード。 ぎりぎり自分のAirが対応リストに入ってたからよかった。

そのあとXcode 10.1を再ダウロード&インストールした。6GB弱あるので、インストール完了まで随分と時間がかかった。

一応、めでたくチュートリアルのサンプルが動いた(まだ途中だが)。

まとめると

以上。

Linux Mint日本語環境(US配列キーボード)

最近Linux Mintを使い始めた。古いiMacにインストール。 しかし、ブート領域を上書きされてMac OS Xの環境がおかしくなってしまった。 まあもうほとんど使わないからいいか。Linux MintGUIシンプルだし超サクサクだし、自分好みだわ。

さて、最近まで日本語入力環境がいまいちだったのが、やっとまともな環境になった。 自分はUS配列キーボードを使っているから苦労している、というのもあるかもしれん。

とりあえず、うまく行った設定のメモ。

1. Input MethodはIBusを使う

Menu->Control Center->Input Method で設定できる。

2. IBUS ReferenceでMozを追加

Menu->Search:でIBUSを入力すると項目が出てくるの選ぶと設定ダイアログが出てくる。

このサイトを参照: https://qiita.com/Justmeaning/items/17fdd149952d6785b23d

3. IME起動のホットキーの定義を変更

このサイトを参照:   Ubuntu17.10で「日本語入力と英語入力」を切り替える方法

Linux Mintの場合タスクバーの右に「あ」というアイコンが現れるので、 左クリックしてTools->Propertiesを選び、ダイアログのGeneralタブのKeymap style のCustomize...を選ぶ。

もとのCtrl Spaceの設定を消して、Hankaku/Zenkakuと設定されている項目をCtrl Spaceに置き換える。


これでCtrl + Spaceで変換・無変換の切り替えができるようになった。 素晴らしい。

ちなみにInput MethodにFcitxも選べるが、こっちの方はぜんぜんダメだった。 設定メニューすらうまく起動できなかった。

以上。

STM32F103 Nucleo開発環境リンクメモ

STM32F103 NucleoボードでLチカまでやったが、このレベルでもMPUがリッチすぎるな。 H/WダイレクトのBare metal progurammingをやろうとすると面倒。 メーカー提供のライブラリを使わないとLチカするのも大変。もう少しシンプルなので遊びたいなと。

とりあえず環境の導入に参考になったサイトのメモ。

RaspberryPiでSTM32開発環境の構築

フリーだけの開発環境(gcc)の導入で参考にした。

Home · OliviliK/STM32F103 Wiki · GitHub

libopencmというライブラリ開発してる。これが便利そう。

  Lチカは結局ここのひとつの記事を参考にした。

  Tutorial3_GPIO · OliviliK/STM32F103 Wiki · GitHub

SunMoonSim/STM32F103-MD.ld at master · barrybingo/SunMoonSim · GitHub

STM32F103のlinker scriptが置いてある。

GitHub - avislab/STM32F103: STM32F103C8 Examples

STM32F103の初期化コード(startupルーチンとか)が置いてある。

以上。

STM32 Nucleo Board買う

久々に寄った秋月でSTM32 Nucleoボードを購入した。 ボードのデザインに惹かれ、調べたら中身もなかなか良さげだったので、ほとんど衝動買い。 ジャケ買いみたいなもんだな。

STM32 Nucleo Board STM32F103: マイコン関連 秋月電子通商-電子部品・ネット通販

Coretex-M3積みで1500円という驚きの安さ。 Arduinoより安い。この系統のマイコンボードの中では一番安いシリーズではなかろうか。

さて、ここ2、3日は環境構築。 STM32は結構昔から出てるから情報も多く、メーカーから出している開発環境もかなり充実してる感じ。 オープンソース環境ではEclipse + CDT + ARMクロス環境が定番のようで、ネットにも Eclipseの環境のセッティング方法が転がっていたが、ビルド→実行までいろいろ面倒そうだ。

結局、下記の記事を参考にCLI環境を構築した。

RaspberryPiでSTM32開発環境の構築

自分のMac環境だとARMのクロスコンパイラは入れてたから、結局ST-LINKを新たに入れただけだった。 (これもbrew install stlinkを打つだけだった)

ボードのマニュアル読むと、これぐらいシンプルなのは自分にとってはいいな。

スペック:

・最高動作クロック:72MHz
・内部メモリ:128KB(Flash)、20KB(SRAM)

もいいねえ。 20KBはちと狭いが、SPI RAMつけて遊ぶのも面白そうだ。

teensy 3.5でbare metal programmingことはじめ

ちとベアメタルプログラミングしたくなって、いい感じのマイコンボードないかと探していたら、teensyというのが、ARM Cortex-M4を使っていて手軽そうだったので購入してみた。

DEV-14055 Teensy USB Development Board - Teensy 3.5

標準ではArduino IDE環境を使う。Arduino環境にteensyの環境を上乗せしている感じ。 (手順はteensyのサイトに書いてある)

これだとC言語アセンブラで書いたコードのビルド方法がわからない。 ネット上で探しても最新の環境に合う手順書はなかった。

色々試してたが、結果的にそんなに大変でもなかった。

以下が最短距離メモ。 Arduino環境をインストールしなくてもTeensy向けのバイナリをビルド可能。

(1) ARMから最新の組み込みクロス開発環境をダウンロード

https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads

Max OS X 64bitの結局tar.bz2を展開して、/usr/local/に放り込んだだけ。 あとはPATHを通しして終わり。

(2) Teensyのcore ライブラリのソースをゲットする

https://github.com/PaulStoffregen/cores

このPaulStoffregenのリポジトリはどういうものなのか、よく分かっていないが、 Arduino開発環境を使わない環境とMakefileがゲットできる。 (Makefileのオプション指定でArduinoを使用しないようにする。)

(3) 上記の中の、teensy3/ に入ってビルド

Makefileのビルドターゲットがmain.cppになっていて、これはLEDチカをやっているサンプルコード。

$ export COMPILERPATH=/usr/local/arm-none-eabi
$ export NO_ARDUINO=1
$ make

main.hexができるので、これをTeensy Loaderで実機にダウンロードして実行。

以上。

Haskellでミニマムな正規表現のmatch関数を実装してみる

「ビューティフルコード」(オーライリー・ジャパン)のしょっぱなの章で、 カーニハン先生がロブ・パイクさんのミニマムな正規表現のmatch関数のソースコードを紹介していた。

たった30行ほどのC言語コードで、下記正規表現をサポートする。

文字 意味
c 文字cそのもの
. 任意の一文字
^ 文字列の先頭にマッチ
$ 文字列の末尾にマッチ
* 直前の文字の0回以上の反復

95%の用途はこれで足りると書いてあったが、さもありなん。 短くて日常のほとんどのケースで用が足せる簡潔なプログラムは、まさにUNIX精神そのもの。

この本のパイクさんのコードに触発されて、Haskellで同等のものを書いてみた。

ミニマム正規表現match関数Haskell

match_here :: [Char] -> [Char] -> Bool
match_here [] _ = True
match_here (x:xs) []
    | x == '$' && xs == [] = True
    | otherwise = False
match_here (x:xs) (y:ys)
    | x == y || x == '.' = if xs /= [] && head xs == '*' 
                           then match_repeat x (tail xs) ys
                           else match_here xs ys
    | otherwise = False


match_repeat :: Char -> [Char] -> [Char] -> Bool
match_repeat _ [] _ = True
match_repeat _ _ [] = False 
match_repeat c (x:xs) (y:ys)
    | x == y = match_here xs ys
    | c == y || c == '.' = match_repeat c (x:xs) ys
    | otherwise = match_here xs (y:ys)


-- match regex string 
match :: [Char] -> [Char] -> Bool
match _ [] = False
match (x:xs) (y:ys)
    | x == '^' = match_here xs (y:ys)
    | match_here (x:xs) (y:ys) = True
    | otherwise = match (x:xs) ys

使用例

*Main> match "^a.*1" "abccfb1"
True
*Main> match "abc" "abccfb1"
True
*Main> match "c.*1$" "abccfb1"
True
*Main> match "ccd" "abccfb1"
False

ロブ・パイクさんのコードは、再帰とポインタを巧みに使っていて、 ほとんどC言語関数型プログラミングをしているようなもの。

このプログラム構成のアイディアはそのまま使った感じだが、 コードを見ながら移植だとつまらないので、 一度みた構成を思い出しながら、Haskellで実装するというスタイルをとった。

Haskell初心者なので、実はもっと簡潔に書けるかもしれない。 が、実際書いてみるとHaskell言語はかなり見通しがよいと思った。 パターンマッチング、条件分岐や関数宣言の簡潔な記法、が効いているな。

続:Haskell/Clojureでrepeated_combinationを実装してみる

http://hifistar.hatenablog.com/entry/2018/03/24/131654:repeat_combinationを実装してみるの続き。

この前書いたコードは結構無駄が多くて、実はもっとぜんぜん簡潔にコードが書けた。 ここまで簡潔なコードにブラッシュアップできたのは、Haskellのおかげだなと。

Clojureだけの場合は、ある程度で満足して、先に思考を進めることはあまりしなかった。 Haskellでコードを書くと、違う視点でものごとを考えることができる、というのが大きい。

Haskellは、文字通り「型にはまる」とコードがものすごくシンプルになる、と実感する。 関数のInput/Outputの型(データの抽象度のレベル感)を揃えることが、が非常に大事だと学んだ。

これはプログラミングの基本中の基本かもしれないが、なかなか意識しても難しい。 Haskellの場合は強制的にそれをさせる、という意味でかなり良い。

Clojureの場合は、そろってなくてもプログラムが組める。自由度が高い。 ifなどの条件文で動的に型をチェックして、処理を振り分けてしまえる。 これはもろ刃の剣で、素早くコードを組んだり変更したりするには向いているが、かなり意識しないとプログラムの構造がmessyになる。

双方をやることでいろいろ気づきが出てきて、「結局こういうことじゃね?」という風に理解が深まる。 短いコードで表現できるアルゴリズム系の勉強に、結構いいんじゃなかろうかと思った。

さて、あらためてrepeat_combinationの実行例:

*Main> repeat_combination [1,2,3] 2
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
*Main> repeat_combination [1,2,3] 3
[[1,1,1],[1,1,2],[1,1,3],[1,2,1],[1,2,2],[1,2,3],[1,3,1],[1,3,2],[1,3,3],[2,1,1],[2,1,2],[2,1,3],[2,2,1],[2,2,2],[2,2,3],[2,3,1],[2,3,2],[2,3,3],[3,1,1],[3,1,2],[3,1,3],[3,2,1],[3,2,2],[3,2,3],[3,3,1],[3,3,2],[3,3,3]]
幅優先で組み合わせする場合

結局こういうことだ。(「幅優先」という表現が合っているか微妙だが)

Haskell
repeat_combination :: [Int] -> Int -> [[Int]]
repeat_combination xs 0 = [[]]
repeat_combination xs n = [ x : y | x <- xs, y <- repeat_combination xs (n-1)]
Clojure
(defn repeat-combination [xs n]
  (if (= n 0)
    [[]]
    (for [x xs
          y (repeat-combination xs (dec n))]
       (cons x y))))

上記は、組み合わせた結果の帰り値に対して、さらに組み合わせを計算する。

末尾最適化可能なやり方

同じ幅優先だが、こちらは引数に結果を渡すやり方で、これだと末尾最適化できる。

Haskell
combination :: [Int] -> [[Int]] -> Int -> [[Int]]
combination xs ys 0 = ys
combination xs ys n = combination xs [ x : y | x <- xs, y <- ys ] (n-1)

repeat_combination :: [Int] -> Int -> [[Int]]
repeat_combination xs n = combination xs [[]] n
Clojure
(defn combination [xs ys n]
  (if (= n 0)
    ys
    (recur xs
           (for [x xs, y ys] (cons x y))
           (dec n))))

(defn repeat-combination [xs n]
  (combination xs [[]] n))
深さ優先で組み合わせる場合

これも引数に結果を渡して繰り返すやり方。

Haskell
combination xs ys 0 = [ys]
combination xs ys n = concat [combination xs (ys++[x]) (n-1) | x <- xs]

repeat_combination :: [Int] -> Int -> [[Int]]
repeat_combination xs n = combination xs [] n
Clojure
(defn combination [xs ys n]
  (if (= n 0)
    [ys]
    (apply concat
           (for [x xs] (combination xs (conj ys x) (dec n))))))

(defn repeat-combination [xs n]
  (combination xs [] n))

concatが美しさを損ねているが、まあしょうがない・・・。


ひとつ選ぶとしたら、分かりやすさと簡潔さ、プラスStack Overflowにならないので、2番目のやり方かなあ。