Raspberry Pi3 Model BとRaspberryPI用3.5inchタッチ液晶(LCD)のセットアップ
Raspberry Pi3 Model Bを購入したついでにタッチ液晶(LCD)も購入したのですが、 ちょっと設定に苦戦したのブログに残しておきます。
買ったもの
- Raspberry Pi3 Model B ボード&ケースセット 3ple Decker対応 (Element14版, Clear)-Physical Computing Lab
- Elecrow3.5インチタッチパネル タッチスクリーンディスプレイ480X320解像度 TFTモニター LCDタッチスクリーンキット Raspberry Pi B+/2B Raspberry Pi 3B対応
- SanDisk Extreme Pro microSDHC UHS-I カード Class10 16GB SDSDQXP-016G-J35
やり方
1) イメージダウンロード
まず、Raspberry Piの公式ページからRaspbianのイメージをダウンロードします。 ここで気をつけたいのがNOOBSじゃなくてRaspbianのイメージを使うことです。 現時点(2017年2月4日)では、NOOBSだとタッチ液晶(LCD)のパッチの相性が悪くてうまく動かず、Raspbianだとうまく動きました。
ダウンロードしたファイル(2017-01-11-raspbian-jessie.zip)を解凍します。ダウンロードページに書いてある通り7ZipやThe Unarchiverで解凍するのが楽でした。
2) SDカードに書き込み
SDカードをフォーマットし、ddコマンドでイメージを書き込みます。
※ dfコマンドでは「/dev/disk2s2」になっていますが、ddコマンドで書き込むときは「/dev/rdisk2」にします(先頭にrを付け、末尾のs2を取り除く)。
3) Raspberry Pi起動
USBキーボード、USBマウス、SDカード、有線LANケーブル、HDMIケーブルをRaspberry Piに繋ぎ、最後にMicro-USBケーブルを繋ぎます。 SDカードに正しくイメージが書き込まれていれば、Micro-USBケーブルを繋ぐだけで勝手に起動してくれます。 LANが有線であれば特に設定を行うことなく、インターネットに接続できるはずです。
4) LCDのパッチを当てる
Raspberry Pi上でTerminalを起動し、以下のコマンドを順に実行します。
$ sudo raspi-config $ wget http://www.waveshare.com/w/upload/4/4b/LCD-show-161112.tar.gz $ tar zxf LCD-show-161112.tar.gz $ cd ./LCD-show $ ./LCD35-show
sudo raspi-config
の際は、
- 「Expand Filesystem」を選択
- 「Boot Option」を選択して「Desktop Autologin」を選択
を行います。
そして、Raspberry Piにタッチ液晶を接続し、再起動して完了です。
ちなみに、3.5inchのタッチ液晶に対してLCD32-show
を実行してしまうと再起動後Raspberry Piの起動が失敗します。
LCD??-show
のコマンドはくれぐれも間違わないように!
参考にしたもの
- http://jellyware.jp/kurage/raspi/lcd_32inch.html
- http://qiita.com/starswirl_k/items/62fab45afccf8ffff2f7
- http://qiita.com/loopsketch/items/4c7169b9c4373e6da4d0
- http://www.waveshare.com/wiki/3.5inch_RPi_LCD_(A)
- http://cabbalog.blogspot.jp/2016/06/raspberry-pi-us-keyboard.html
- http://d.hatena.ne.jp/muupan/20130124/1359006615
Vimconf 2016に参加した。
Vimconf2016に参加してきました。 本編は午後からなんだけど、一応スタッフということもあって午前中から会場入りした。
http://vimconf.vim-jp.org/2016/
http://vim-jp.org/blog/2016/10/31/announce-vimconf2016-before-event.html
発表者の各内容は公式サイトにあるので省きますが、参加して思ったことなどをいくつか。
- 「vim-mode-plus for Atom editor」はt9mdさんのVimに対する理解度がやばかった。この発表、「テキストオブジェクト」や 「モーション」などのVim専門用語がバンバン使って話されていて、「これ理解して聴いている人、この中の何割くらいだ?」って思うほど濃かった。
- koronさんは「Vimの日本語ドキュメント」について発表していたけど、backspacefm vim-sideの次のネタなんじゃ?って思っていながら聴いていたw。次のbackspacefm vim-side #3も同じネタ話すんかな?日本語入力だったけ?
- Go関連の話が多かった。
koronさん提供のVimリストバンド。
技術イベントでおなじみの寿司🍣 とピザ🍕。今回は綺麗に食べきれた。ジュースは1.5Lのが8本前後余ったけど。
私作成の名札。前年度と比べるとちょっと品質向上した。
発表者のスライドの文字サイズが小さい問題。Vimconf2015のujmさんのスライドの文字サイズくらいがよさそう、今後の参考にしたい。
- セキココと会場のイスレイアウトの相性の悪さ。
- カメラ提供、vikkeさんありがとうございました。
- b4b4r07さんのアイコンと実際の本人とのギャップ。
- AP回復アイテム(座布団とか)が必要。
以上、お疲れ様でした。
ファイルに保存されたマクロを動的にロードする方法(Excel VBA)
以下のコードでファイルに保存されたマクロを動的にロード出来ます。 ちょっとめんどくさいのは、デフォルト設定のExcelでは「プログラミングによる Visual Basic プロジェクトへのアクセスは信頼性に欠けます」の実行時エラーになってしまい、実行できません。 なので、「マクロの設定」の「VBA プロジェクトオブジェクトモデルへのアクセスを信頼する」をチェックしないといけません。
ThisWorkbookシート
Option Explicit ' --------------------------------------------- ' ファイルに保存されたマクロを動的にロードする。 ' --------------------------------------------- Private Sub Workbook_Open() Call ClearModules Call ImportModule(ThisWorkbook.Path & "\ModMain.bas") End Sub Private Sub Workbook_Close() Call ClearModules End Sub Private Sub ImportModule(ByVal strFilePath As String) Dim objFS As Object Set objFS = CreateObject("Scripting.FileSystemObject") If objFS.FileExists(strFilePath) Then ThisWorkbook.VBProject.VBComponents.Import strFilePath Else Call MsgBox("モジュールが存在しません。" & vbCrLf & strFilePath) End If Set objFS = Nothing End Sub Private Sub ClearModules() Dim varComponent As Variant For Each varComponent In ThisWorkbook.VBProject.VBComponents If varComponent.Type = 1 Then ThisWorkbook.VBProject.VBComponents.Remove varComponent End If Next End Sub ' 【Excel】実行エラー「プログラミングによる Visual Basic プロジェクトへのアクセスは信頼性に欠けます」の対策 ' http://saku-saku-pc.com/excel/プログラミングによるアクセス/
Microsoft Visual Studio 14.0でVimをビルドする。
今までMacBook AirのTerminal上でvimをビルドするか、もしくはWindowsのMinGWでビルドしていました。 今回、Microsoft Visual Studio 14.0でビルドをしてみました。 で、ビルドしてみたけど結構はまりどころがあったのでここに適当にまとめます。
まず、最終的にできた私のビルドスクリプトを載せておきます。
vimbuild.bat
@echo off set PATH=%SystemRoot% set PATH=%PATH%;%SystemRoot%\System32 set PATH=%PATH%;%SystemRoot%\System32\Wbem set PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin set INCLUDE= set LIBPATH= call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat" set OPT1= IME=yes MBYTE=yes ICONV=yes CSCOPE=yes NETBEANS=no set OPT2= PLATFORM=x86 SDK_INCLUDE_DIR="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include" XPM=no pushd .\vim\src nmake -f Make_mvc.mak %OPT1% %OPT2% GUI=no clean nmake -f Make_mvc.mak %OPT1% %OPT2% GUI=yes clean nmake -f Make_mvc.mak %OPT1% %OPT2% GUI=no nmake -f Make_mvc.mak %OPT1% %OPT2% GUI=yes popd
はまりどころ
Microsoft Visual Studio 14.0でVimをビルドする上で注意した方がいいオプションが以下になります。
INCLUDE, LIBPATH
これは直接的にはVimに関係ないけど、vcvars32.bat
はINCLUDE
とLIBPATH
にどんどん値を追加していくようになっていて、
vcvars32.bat
を20回くらい呼ぶと限界を超え、以下のエラーになります。
入力行が長すぎます。 コマンドの構文が誤っています。
なので、vcvars32.bat
を呼ぶ前に初期化しておくとよいです。
set INCLUDE= set LIBPATH= call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\vcvars32.bat"
PLATFORM
私のビルド環境がPLATFORM=MCD
だったのですが、Make_mvc.mak
はMCDのプラットフォームに対応してないっぽいので
以下のエラーになってしまいました。
Microsoft(R) Program Maintenance Utility Version 14.00.23918.0 Copyright (C) Microsoft Corporation. All rights reserved. Make_mvc.mak(228) : fatal error U1050: *** ERROR Unknown target platform "MCD". Make aborted. Stop.
なので、私は対応しているPLATFORM=x86
にして対処してみました。
PLATFORM=x86
SDK_INCLUDE_DIR
ビルドにはWin32.mak
を必要らしく、SDK_INCLUDE_DIR
を設定していないと以下のエラーになってしまいます。
Microsoft(R) Program Maintenance Utility Version 14.00.23918.0 Copyright (C) Microsoft Corporation. All rights reserved. Make_mvc.mak(254) : fatal error U1052: ファイル 'Win32.mak' が見つかりません。 Stop.
なので、SDK_INCLUDE_DIR
にWin32.mak
があるフォルダを指定します。
SDK_INCLUDE_DIR="C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include"
XPM
Vimはpre-compiledなXPMがレポジトリに含まれていて、それがLIBC.libにリンクしているみたいです。
@rbtnn 恐ろしいことにXPMはpre-compiledなライブラリがVimのレポジトリに含まれてるんですよ。それがLIBC.libにリンクしているという寸法でして。
— MURAOKA Taro (@kaoriya) 2016年6月25日
最近のMicrosoft Visual StudioはLIBC.libを含んでいないため、以下のようなエラーが出てしまいます。
link /RELEASE /nologo /subsystem:windows /LTCG:STATUS -out:gvim.exe .\ObjGi386\blowfish.obj .\ObjGi386\buffer.obj .\ObjGi386\charset.obj .\ObjGi386\crypt.obj .\ObjGi386\crypt_zip.obj .\ObjGi386\diff.obj .\ObjGi386\digraph.obj .\ObjGi386\edit.obj .\ObjGi386\eval.obj .\ObjGi386\ex_cmds.obj .\ObjGi386\ex_cmds2.obj .\ObjGi386\ex_docmd.obj .\ObjGi386\ex_eval.obj .\ObjGi386\ex_getln.obj .\ObjGi386\fileio.obj .\ObjGi386\fold.obj .\ObjGi386\getchar.obj .\ObjGi386\hardcopy.obj .\ObjGi386\hashtab.obj .\ObjGi386\json.obj .\ObjGi386\main.obj .\ObjGi386\mark.obj .\ObjGi386\mbyte.obj .\ObjGi386\memfile.obj .\ObjGi386\memline.obj .\ObjGi386\menu.obj .\ObjGi386\message.obj .\ObjGi386\misc1.obj .\ObjGi386\misc2.obj .\ObjGi386\move.obj .\ObjGi386\normal.obj .\ObjGi386\ops.obj .\ObjGi386\option.obj .\ObjGi386\os_mswin.obj .\ObjGi386\winclip.obj .\ObjGi386\os_win32.obj .\ObjGi386\pathdef.obj .\ObjGi386\popupmnu.obj .\ObjGi386\quickfix.obj .\ObjGi386\regexp.obj .\ObjGi386\screen.obj .\ObjGi386\search.obj .\ObjGi386\sha256.obj .\ObjGi386\spell.obj .\ObjGi386\syntax.obj .\ObjGi386\tag.obj .\ObjGi386\term.obj .\ObjGi386\ui.obj .\ObjGi386\undo.obj .\ObjGi386\window.obj .\ObjGi386\vim.res .\ObjGi386\gui.obj .\ObjGi386\gui_beval.obj .\ObjGi386\gui_w32.obj .\ObjGi386\os_w32exe.obj .\ObjGi386/if_cscope.obj .\ObjGi386/channel.obj .\ObjGi386/xpm_w32.obj .\ObjGi386\version.obj oldnames.lib kernel32.lib advapi32.lib shell32.lib gdi32.lib comdlg32.lib ole32.lib uuid.lib /machine:i386 gdi32.lib version.lib winspool.lib comctl32.lib advapi32.lib shell32.lib /machine:i386 libcmt.lib user32.lib WSock32.lib xpm\x86\lib\libXpm.lib /PDB:gvim.pdb -debug LINK : fatal error LNK1104: ファイル 'LIBC.lib' を開くことができません。 NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\link.EXE"' : リターン コード '0x450' Stop.
なので、XPM=no
にして対処しました。
環境
- Windows 10 Home Intel(R) Celeron(R) CPU N2840 @ 2.16GHz 2.16GHz 64ビットオペレーティングシステム x64ベースプロセッサ
- Vim 7.4.1913
- cmd.exe (Microsoft Windows [Version 10.0.10586])
dart:core Stringの関数について
dart:core Stringの関数について
ここに書いてある関数について適当に日本語化&例を載せてまとめます。
https://api.dartlang.org/1.13.0/dart-core/String-class.html
まとめるほどでもないけど、単純にどんな言語でも文字列操作大事だし、まぁ単純にアウトプットしたいだけです。 あと、Iterableをリストと表記したりかなり雑です。
コンストラクタ
String.fromCharCode(int charCode) factory
数値から文字列を生成する。
main(){ var c = new String.fromCharCode(0x41); print(c); // A }
String.fromCharCodes(Iterable<int> charCodes, [int start = 0, int end]) factory
数値のリストから文字列を生成する。このリストの始まりと終わりを指定することも可能。
main(){ var ns = [0x41, 0x42, 0x43, 0x44]; print(new String.fromCharCodes(ns)); // ABCD print(new String.fromCharCodes(ns, 1)); // BCD print(new String.fromCharCodes(ns, 1, 2)); // B }
String.fromEnvironment(String name, {String defaultValue}) factory
pub build
時に--define
で定義した値を取得する。
main(){ // `pub build --define releasemode=true`の場合 print(const String.fromEnvironment('releasemode')); // true }
プロパティ
codeUnits -> List<int> read-only
文字列からUTF-16のコードの変更不可なリストを返す。
main(){ var xs = 'hi'.codeUnits; print(xs); // [104, 105] // エラー! // xs[0] = 0x41; }
hashCode -> int read-only
文字列のハッシュ値を返す。
main(){ var hash = 'hi'.hashCode; print(hash); // 793667904 }
isEmpty -> bool read-only
空文字列ならtrue
を返す。
main(){ print('hoge'.isEmpty); // false print(''.isEmpty); // true print(' '.isEmpty); // false }
isNotEmpty -> bool read-only
空文字列でないならtrue
を返す。
main(){ print('hoge'.isNotEmpty); // true print(''.isNotEmpty); // false print(' '.isNotEmpty); // true }
length -> int read-only
文字列の長さを返す。
main(){ print('hoge'.length); // 4 print(''.length); // 0 }
runes -> Runes read-only
main(){ print('hoge'.runes); // (104, 111, 103, 101) for(var c in 'hoge'.runes){ print(c); } // 104 // 111 // 103 // 101 }
runtimeType -> Type read-only, inherited
型名を返す。
class A{} main(){ var a = new A(); print(a.runtimeType); // A print('hoge'.runtimeType); // String }
オペレータ
operator *(int times) -> String
文字列をtimes
回繰り返した文字列を返す。
main(){ print('abc' * 2); // abcabc }
operator +(String other) -> String
文字列同士を結合する。
main(){ print('abc' + 'def'); // abcdef }
operator ==(Object other) -> bool
文字列が同じであるか判定する。
main(){ var a = 'abc'; var b = 'abc'; var c = 'def'; print(a == b); // true print(a == c); // false print(b == c); // false }
operator [](int index) -> String
文字列のindex
番目の文字を取得する。(0オリジン)
main(){ var str = 'abc'; print(str[0]); // a print(str[2]); // c }
メソッド
あとで書く。
Surface Pro 4とArc Touch Mouse for Surface
Surface Pro 4とArc Touch Mouse for Surfaceを買ったのだけど、Arc Touch Mouseのマウスホイールの振動音がうるさい。 なので、その対処方法を書いておく。
※ Wedge Touch Mouse and Arc Touch Mouse for Surface
手順
- スタートメニューからストアを開く。
- 検索のテキストボックスに「Arc Touch Bluetooth Mouse」を入力して検索する。
- アプリをインストールする。Microsoftアカウントが必要。
- スタートメニューから「Arc Touch Bluetooth Mouse」を選択して起動する。
- 振動/サウンドをOFFにする。
「Land of lisp」を読んだのでCommon Lispのまとめ
Land of lispを読んだので、Common Lispについてまとめてみます(以下Common LispのことをLispと表記しています)。 一応私はLisp初心者なので間違いがあるかもしれません。
clisp
まず、Lispの処理系ですが以下のコマンドで一発でインストールできます (clispがメジャーらしい)。
>brew install clisp
>choco install clisp
clispはREPLもできますが、以下のようにソースファイルをインタプリタすることができます。
>clisp a.lisp
clispはソースファイルをコンパイルできますが、出力されるのはネイティブコードではなくバイトコードになります。
>clisp -c a.lisp -o a.fas >clisp a.fas
Lispについて
Lispのコードは簡単にいうとポーランド記法の式を括弧で括って表現されたものです。括弧で括られたものをリストと呼びます。
(+ 1 2) ; 3
コメントアウト
; これはコメントです。
コマンドモードとデータモード
Lispにはコマンドモードとデータモードというものがあって、以下のようなリストはコマンドモードという状態下にあります。
コマンドモードでのリストをフォームとも呼び、フォームの1つ目の要素(ここでは+
に当たる)をコマンドと呼びます。
このコマンドは関数やマクロなど特別なものでないといけません。
(+ 1 2) ; 3
データモードはリストに'
を付けた形となります。コマンドモードと異なり、1つ目の要素がコマンドである必要はありません。
なのでデータモードでは、リストとしてそのまま評価されます。
'(+ 1 2) ; (+ 1 2) '(1 2 3) ; (1 2 3) '(1 2 3 (4 5)) ; (1 2 3 (4 5)) ; '(...)内のものはすべてデータモードで評価される。
シンボル
Lispにはシンボルという独立した値を表すトークンが存在します。
シンボルに使える文字はアルファベット、数字、そして+
-
/
*
=
<
>
?
!
_
になります。
また、シンボルは基本的にアルファベットの大文字小文字を区別しません。
ただし、|
を使うことで大文字小文字を区別したシンボルを作成することも出来ます。
(princ 'hoge) ; HOGE (princ '|Hello World|) ; Hello World
数値
Lispの数値には整数と浮動小数点数の2種類が存在します。
小数点が含まれていれば浮動小数点数、小数点が含まれていなければ整数として扱われます。
また、Lispでは1
と1.0
が区別されます。
(princ 12) ; 12 (princ 1.23) ; 1.23
文字列
Lispの文字列は文字の集まりを"
で括って表します。
\
と"
を含めたい場合には\
でエスケープします。
(princ "hello") ; hello (print "hello") ; "hello"
文字
Lispの文字リテラルは#\
を付けることで表すことが出来ます。
特殊な文字(改行、タブ、スペース、など)はそれぞれ#\newline
、#\tab
、#\space
で表すことが出来ます。
(princ #\c) ; c (princ #\newline) (princ #\tab) (princ #\space)
グローバル変数
グローバル変数を定義するにはdefparameter
もしくはdefvar
を使います。
(defparameter *hoge* 12)
(defvar *hoge* (+ 3 4))
defparameter
とdefvar
の違いは複数回呼ばれた時に上書きされるかどうかです。
defparameter
はどんどん上書きしていくのに対して、
(defparameter *hoge* 1) (print *hoge*) ; 1 (defparameter *hoge* 2) (print *hoge*) ; 2
defvar
は初回の値を保ち続けます。
(defvar *hoge* 1) (print *hoge*) ; 1 (defvar *hoge* 2) (print *hoge*) ; 1
Lispではグローバル変数を*
で括る文化があるらしい。
また、Lispではグローバル変数のことをダイナミック変数やスペシャル変数とも呼びます。
関数の定義
関数を定義するには(defun 関数名(引数) 本体)
の形式で定義することができます。
(defun add(a b) (+ a b)) (add 1 2) ; 3
ローカル変数とローカル関数
ローカル変数を定義するには(let ((変数名 値) ...) 本体)
の形式で定義することができます。
(let ((x 3) (y 4)) (* x y)) ; 12
ローカル関数を定義するには(flet ((関数名(引数) 本体) ...) 本体)
の形式で定義することができます。
(flet ( (f(x) (1+ x)) ) (f 3)) ; 4
flet
は同レベルで定義されたローカル関数を参照することができません(再帰すらできません)。
なので、同レベルで定義されたローカル関数を参照するローカル関数を定義するにはlabels
を使います。
別のローカル関数を呼ぶ
(labels ( (f(x) (1- x)) (g(x) (* (f x) 2)) ) (g 3)) ; 4
自身のローカル関数を呼ぶ
(labels ( (f(xs) (if xs (+ (car xs) (f (cdr xs))) 0))) (f '(1 2 3))) ; 6
コンスセル
Lispにはコンスセルという単位があります。 コンスセルは値を格納できる箱(スロットと呼ばれる)が2つあるようなものです。
コンスセルのイメージ
[|] / \ 1 2
ちなみにリストはコンスセルの集まりです。
リストはコンスセルが連続して最後の要素がnil
という特別な値で終わるもののことを指します。
リストのイメージ
[|] / \ 1 [|] / \ 2 [|] / \ 3 nil
コンスセルを作成するにはcons
か.
で作成することが出来ます。
(cons 1 2) ; (1 . 2) '(1 . 2) ; (1 . 2)
リストはコンスセルの集まりなので、以下のようにリスト作ることも出来ます。
'(1 . (2 . nil)) ; (1 2) '(1 2) ; (1 2)
真理値
Lispには特別なシンボルT
とnil
があります。T
が真値、nil
が偽値と評価されます。
(if T 1 2) ; 1 (if nil 1 2) ; 2
実はLispではnil
、'nil
、()
、'()
が同じ意味を持ち偽値と評価され、これ以外のすべて値が真値と評価されます。
(if '(1 2) 1 2) ; 1 (if () 1 2) ; 2
carとcdr
Lispにはリストから値を取り出す関数car
とcdr
があります。
car
は先頭の要素を返し、cdr
は残りの要素をリストで返します。
(car '(1 2 3 4 5)) ; 1 (cdr '(1 2 3 4 5)) ; (2 3 4 5)
car
もcdr
も、正確にはコンスセルを扱う関数なので以下のようにコンスセルから値を取り出すことも出来ます。
(car '(1 . 2)) ; 1 (cdr '(1 . 2)) ; 2
リストにcdr
を適用すると末尾にnil
が付属するため結果がリストになりますが、
コンスセルにcdr
を適用しても末尾にnil
が付属しないため結果がリストになるとは限りません。
(cdr '(1 2)) ; (2) (cdr '(1 . 2)) ; 2 (cdr '(1 . (2 . nil))) ; (2)
Lispにはcar
やcdr
のほかにcdar
のような/c[ad]+r/の関数が用意されています(どのくらいの長さまで用意されているかは処理系による)。
(cadr '(1 2 3 4)) ; 2 (cadddr '(1 2 3 4)) ; 4 (cddddr '(1 2 3 4)) ; nil (caar '((1 2) 3 4)) ; 1
eqとequal
Lispには同じかどうか比較する関数がいくつか存在します。 とりあえず、以下のルールにしたがって使えばよいらしい。
- シンボル同士は常に
eq
で比較すべし。 - シンボル同士でなければ
equal
を使え。
ちなみにequal
は内部で型分岐をしていて、数値なら=
、文字列ならstring-equal
、文字ならchar-equal
を使っています。
なので、処理速度を求めるなら、これらを直接呼んだ方が良いです。
準クオート
Lispの'
によってコマンドモードからデータモードに移行することはできますが、
データモードからコマンドモードに移行することはできません。
そのため、Lispには`
と,
を使ってデータモードからコマンドモードへと移行出来る仕組みが存在します。
`(1 2 ,(car '(3 4)) 5) ; (1 2 3 5)
このように、`
でデータモードが開始され、,
で一時的にコマンドモードへと戻ることが出来ます。
関数オペレータ
Lispは関数を値として扱うことが出来ます。例えば、mapcar
関数は関数とリストを1つずつ受け取り、
そのリストの各要素に関数を適用した新たなリストを返す関数です。
その際、関数を値として認識させるために関数オペレータ#'
もしくはfunction
関数を使用します。
mapcar
関数のような関数を値として扱うような関数を高階関数と呼びます。
(mapcar #'sqrt '(1 2 3 4)) ; (1 1.4142135 1.7320508 2) (mapcar (function car) '((a b) (c d) (e f) (g h))) ; (A C E G)
ラムダ式
Lispで関数を定義するにはdefun
関数のような関数を使います。しかし、これらの関数は関数名を指定しなくてはなりません。
高階関数を使う際にわざわざ関数名を指定するのは億劫なので、Lispにはラムダ式というlambda
を使って即座に名前なしの関数を作成することが出来ます。
(mapcar (lambda (x) (* x 2)) '(1 2 3 4)) ; (2 4 6 8)
循環リスト
リストの末尾のnil
をリストの先頭にしてやることで循環リストという循環したコンスセルを作成することが出来ます。
循環リストのイメージ
+--------+ v | [|] | / \ | 1 [|] | / \ | 2 [|] | / \ | 3 +--+
; clispの処理系に「これから循環リストを表示するよ」と伝える必要がある。 (setf *print-circle* t) (defparameter *foo* '(1 2 3 4)) (setf (cddddr *foo*) *foo*) (print *foo*) ; #1=(1 2 3 4 . #1#)
配列
Lispにはリストの他に配列も用意されています。配列はリストより要素に速くアクセスすることが出来ます。
配列を作成するにはmake-array
で作成することが出来ます。引数にはその配列のサイズを指定します。
配列の要素を参照する方法はaref
を使い、値を設定するにはaref
とsetf
を使います。
(defparameter *ary* (make-array 3)) (print *ary*) ; #(nil nil nil) (setf (aref *ary* 1) 3) (print *ary*) ; #(nil 3 nil) (print (aref *ary* 1)) ; 3
ハッシュテーブル
Lispにはハッシュテーブルも用意されています(連想リストとは別物です)。
ハッシュテーブルを作成するにはmake-hash-table
を使います。
ハッシュテーブルのキーを参照する方法はgethash
を使い、キーの値を設定するにはgethash
とsetf
を使います。
(defparameter *hash* (make-hash-table)) (print *hash*) ; #S(HASH-TABLE :TEST FASTHASH-EQL) (setf (gethash 'foo *hash*) 3) (print (gethash 'foo *hash*)) ; 3
構造体
Lispには構造体も用意されています。
構造体を定義するには(defstruct 構造体名 メンバ...)
の形式で定義することができます。
構造体が定義されると自動的に構造体を作成する関数と各メンバを参照する関数が定義されます。
(defstruct person name age) (defparameter *p* (make-person :name "bob" :age 32)) (print *p*) ; #S(PERSON :NAME "bob" :AGE 32) (print (person-age *p*)) ; 32
マクロ
LispにはC言語の#define
のような強力なマクロが存在します。
マクロを定義するには(defmacro マクロ名 (引数) 本体)
とdefun
と似た感じで定義出来ます。
マクロ例1
(defmacro m1 (f n1 &rest rest) `(+ ,@rest) ) (print (m1 cdr 1 2 3)) ; 5
&rest
はrest
に残りの引数を1つのリストにしますよと伝えるためのものです。
なのでここでは、f
にcdr
、n1
に1
、rest
に(2 3)
が入ります。
ここでrest
に@
を付け加えることで2 3
と括弧を取り除いた状態で展開することが出来ます。
よって、このマクロを展開すると(+ 2 3)
という形になり、5
が出力されます。
マクロ例2
(defmacro m2 (&rest rest) `(list ,@rest) ) (print (macroexpand (m2 1 2 3))) ; (1 2 3)
macroexpand
はマクロ展開後の状態を文字列として返す便利なマクロです。
マクロ例3
(defmacro m3 (f n1 &rest rest) `(,f ',rest) ) (print (m3 cdr 1 2 3 4)) ; (3 4)
主な関数やマクロ
time
引数に指定された要素の評価した処理時間を求める。
(time (+ 1 2)) ; Real time: 2.1E-5 sec. ; Run time: 1.7E-5 sec. ; Space: 0 Bytes
substitute-if
引数に指定された述語にマッチした要素を置換して返す。
(substitute-if #\- (lambda (x) (equal x #\3)) "1234") ; "12-4" (substitute-if 'x (lambda (x) (eq x 'c)) '(a b c)) ; (A B X)
assoc
連想リスト(alistと呼ばれる)からキーにマッチする要素を返す。
(assoc 'hoge '((foo (1 2)) (hoge (3 4)))) ; (HOGE (3 4))
push
リストを保持している変数の先頭に要素を追加する。
(defparameter *foo* '((a 1) (b 2))) (princ *foo*) ; ((a 1) (b 2)) (push '(c 3) *foo*) (princ *foo*) ; ((c 3) (a 1) (b 2))
setf
変数に値を代入する。
(defparameter *foo* '(1 4)) (setf *foo* (cons 7 *foo*)) (princ *foo*) ; (7 1 4)
find
リストの各要素に:key
で指定された関数を適用した結果に対して第1引数の要素を探す。
(find 'b '((a 1) (b 2) (c 3) (d 4)) :key #'car) ; (B 2) (find 'e '((a 1) (b 2) (c 3) (d 4)) :key #'car) ; nil
remove-if-not
リストの各要素に関数を適用した結果が偽の要素を取り除いた新たなリストを返す。
; 奇数でない要素を取り除く。 (remove-if-not #'oddp '(1 2 3 4)) ; (1 3)
mapcar
リストの各要素に関数を適用した新たなリストを返す。
(mapcar #'sqrt '(1 2 3 4)) ; (1 1.4142135 1.7320508 2)
sqrt
平方根を計算する。
(sqrt 2) ; 1.4142135
expt
べき乗を計算する。
(expt 2 3) ; 8
if
条件分岐を行う。
(if T 1 2) ; 1 (if nil 1 2) ; 2 (if () (princ "good") (princ "bad")) ; bad
when
真の場合のみ処理を実施する。
(when T (princ "bad")) ; bad (when nil (princ "good"))
unless
偽の場合のみ処理を実施する。
(unless T (princ "bad")) (unless nil (princ "good")) ; good
cond
条件分岐を行う。
(let ((x 2)) (cond ((eq x 1) "A") ((eq x 2) "B") ((eq x 3) "C") (t "-"))) ; "B"
case
条件分岐を行う。
(let ((x 2)) (case x (1 "A") (2 "B") (3 "C") (otherwise "-"))) ; "B"
and
AND演算を行う。
(and) ; T (and T nil) ; nil (and T T T T) ; T (and nil nil nil) ; nil
or
OR演算を行う。
(or) ; nil (or T nil) ; T (or T T T T) ; T (or nil nil nil) ; nil
append
リスト同士を結合する。
(append '(1 2) '(3 4)) ; (1 2 3 4) (append '(1 2) 3) ; (1 2 . 3)
member
リストから要素を探す。 もし見つかったなら、その位置から末尾までのリストを返す。
(member 1 '(1 2 3 4)) ; (1 2 3 4) (member 3 '(1 2 3 4)) ; (3 4) (member 0 '(1 2 3 4)) ; nil (member 5 '(1 2 3 4)) ; nil
find-if
リストから述語にマッチする最初に見つかった要素を返す。
(find-if 'oddp '(2 3 2 2)) ; 3
progn
複数の処理を1つにまとめる。
(if () (princ "good") (progn (princ "too") (princ " ") (princ "bad")) ) ; too bad
oddp
奇数ならT
を返し、偶数ならnil
を返す。
(oddp 1) ; T (oddp 2) ; nil
evenp
偶数ならT
を返し、奇数ならnil
を返す。
(evenp 2) ; T (evenp 1) ; nil
random
0からN-1の間の値をランダムに返す。
(random 4) ; 3 (random 4) ; 0 (random 4) ; 2 (random 4) ; 1
length
リストの長さを返す。
(length '(1 2 3 4)) ; 4
nth
N番目の要素を返す(0オリジン)。
(nth 3 '(1 2 3 4)) ; 4 (nth 0 '(1 2 3 4)) ; 1 (nth 2 '(1 2 3 4)) ; 3 (nth 6 '(1 2 3 4)) ; nil
list
引数に与えられたものからリストを作ります。
(list 1 2 3 4) ; (1 2 3 4)
load
別のソースファイルを読み込みます。
(load "b.lisp")
read
ユーザーからEnterキーが押されるまで入力を受けつける。 入力された文字列に応じて、シンボル、数値、文字列などに変換して返す。
(read) hoge ; HOGE (read) 123 ; 123 (read) "key" ; "key"
read-from-string
read
関数の文字列版。
文字列に応じて、シンボル、数値、文字列などに変換して返す。
(read-from-string "hoge") ; HOGE (read-from-string "123") ; 123 (read-from-string "\"key\"") ; "key"
concatenate
引数に応じてシーケンス同士の連結を行う。
(concatenate 'string "hoge" "foo") ; "hogefoo" (concatenate 'list '(2) '(1)) ; (2 1)
char-downcase
文字を小文字に変換する。
(char-downcase #\C) ; #\c
char-downcase
文字を大文字に変換する。
(char-upcase #\c) ; #\C
eval
引数に指定されたデータを評価し、その値を返す。
(eval '(+ 1 2)) ; 3
read-line
ユーザーからEnterキーが押されるまで入力を受ける。 入力された文字列を1つの文字列として解釈する。
(read-line) hoge ; "hoge" (read-line) 123 ; "123" (read-line) "key" ; "\"key\""
print
半角スペースと改行付きで値をそのまま標準出力する。
(print "hey") ; "hey"
prin1
print
関数の半角スペースと改行が付かない版。
(prin1 "hey") ; "hey"
princ
値を人間に分かりやすい形で標準出力する。
(princ "hey") ; hey
fresh-line
直前の文字が改行出ない場合のみ、改行を出力する。
(fresh-line) ; (fresh-line) (fresh-line) (fresh-line) (fresh-line)
terpri
改行を出力する。
(terpri) ; (terpri) ; (terpri) ; (terpri) ; (terpri) ;
incf
1+
インクリメント。
(1+ 4) ; 5
decf
1-
デクリメント。
(1- 4) ; 3
ash
Bitシフト。
; 左に1bitシフトする。 (ash 11 1) ; 22 ; 右に1bitシフトする。 (ash 11 -1) ; 5
終わり
まだ、loopマクロ、format関数、ストリーム、など説明してない項目がありますが、ある程度はまとめられたと思うので終わり。