ソフトウェア第二のまとめ4/10~24

ソフトウェアの授業で学んだことを備忘録的にまとめます。

4/10 Linuxの使い方

  • Terminal
    Terminalの立ち上げは[Ctrl]+[SHIFT]+[T]

  • shellコマンド
    リダイレクト: 標準入出力をファイルから、あるいはファイルへ行う
      command > file でfileに標準出力(上書き)
      command >> file でfileに標準出力(追加)
      (標準エラー出力も共に切り替えるためには >&, >>& とする)
      command < file でfileから標準入力
      
    パイプ: 標準出力を別のコマンドの標準入力へ接続する
      command1 | command2 | …

  • Emacs, vi の使い方、ショートカットキー

  • Java, Perl, Python, Go のサンプルプログラム

  • Makefile の基本的な使い方

4/17 デバッグ

  • コメントを付ける

  • インデントをする

  • プリント文デバッグ
    正しくプログラムが動いているか、print文で記述する。
    print文を削除するためにプリプロセッサを用いるか、コマンドラインスイッチを用いる。

プリプロセッサ

//コンパイルの際に gcc -o test -DDEBUG test.c などとすると...部分が実行される。
#ifdef DEBUG
...
#endif

コマンドラインスイッチ

//実行の際に ./test -d などとすると...部分が実行される
int Debug = 0;

int main(int argc, char *argv[]){
    while(( argc > 1 ) && ( argv[1][0] == '-' )){
        switch (argv[1][1]){
        case 'd':
            Debug = 1; break;
        }
        argc--; argv++;
    }
    
    if(Debug){
        ...
    }
}
  • 対話型デバッガを利用する
    コンパイルの際に -g オプションを付けてgcc -o test -g test.cコンパイルする。
    デバッガを呼び出すときはgdb ./testとすると、行頭に(gdb)と表示されるプロンプトが出てくる。以下、コマンドを示す。
     run: 実行
     bt: 呼ばれた関数をバックトレースすることでプログラムの停止位置がわかる。
     up: 停止位置から関数をさかのぼっていく。
     break (関数名): 関数にブレイクポイントを設定する。この状態でrunをすると設定したブレイクポイントで停止し、print (変数名)で変数に代入されている値を見ることができる。
     next: ステップ実行する。(ステップの単位がよくわからない)
     continue: ブレイクポイントで止まっていた実行を再開する。再びブレイクポイントに差し掛かるとまた停止する。

  • 告白的方法によるデバッグ
    他人にプログラムを説明して解決(しばしば自己解決)する。

  • タイピングソフトtrrの導入
    Emacs用のタイピングソフトtrrを利用してタイピングを早くする。

4/24 EmacsEmacs Lisp

  • バッファとミニバッファの利用
     Emacsを起動すると*scratch*というバッファが起動する。これはLispインタプリタとなっている。実行は行末で[Ctrl]-Jを打ち込む。
     setq: 変数宣言、代入
     defun: 関数の定義。(defun <関数名> (<引数>) <処理>)の形で定義する。
     cond: 複数の条件分岐をする場合に用いる。(cond (<条件1> <処理1>) (<条件2> <処理2>) ... )という形で用いる。常に条件を成立させるためには<条件>をtとする。
     if: 場合分けが二つの場合に用いる。(if <条件> <条件が真のときの処理> <条件が偽の時の処理>)の形で用いる。

  • 線形再帰と線形反復
    線形再帰再帰の元の関数へ収縮しなければ戻り値を渡せないもので、後で実行するものを覚えておかなければいけない。
    線形反復は渡された値から最終的な戻り値が導けるため、覚えておくべき変数が少ない。

  • スコープ
     let: (let (<ローカル変数の定義>) <処理>)の形で用いる。このローカル変数はletの内側でのみ値を保持する。

  • 反復プロセス
     while: (while <条件> <処理>)の形で用いる。  do: (do (( i 0 (+ i 1))) ( >= i 4 ) <処理>)のような形で用いる。Emacs Lispで用いるためには(require 'cl)とする必要がある(らしい)。  dotimes: (dotimes (i 4) <処理>)のような形で用いる。

  • 非ローカル脱出 catch と throw
    (catch <タグ> <処理>)(throw <タグ> <戻り値>)の形で用いる。catchの処理の中で同じタグを持つthrowが出てきたとき、catch の戻り値はthrowの戻り値となる。タグは'(タグの名前)と書く。ここで、'(quote関数の略記)は評価しないことを指示する(らしい)。参考
    同じタグを持つthrowが出てこなかったときは、処理の最後に出てきたタグの名前を返すのだろうか? よくわからない。

  • 無名関数、クロージャ
     lambda式: 名前を持たない関数を定義できる。(lambda (<引数>) <処理>)の形で用いる。
    (setq f #'(lambda ...))や、(funcall #'(lambda ...))など#‘(fanction関数)を用いて評価しないことを指示する。役割としてはquote関数と同じだが、コンパイルするときに便利(らしい)。さらに言えばlambdaはquoteする必要がない(らしい)。参考
    また、funcallは関数を呼び出す関数で基本的にquoteを付けて利用する(らしい)。

  • 手続きの抽象化
    関数を作ってブラックボックス化することで利用しやすくする。
    手続きを扱う手続きを高階手続きという。

  • データの抽象化
    データを組み合わせた合成データを作ることでデータを抽象化する。(具体的には線形結合において、有理数複素数多項式など、さまざまな種類の線形結合を一つの関数で行えるようにできるなどのメリットがある)

  • List
    Emacs Lispでは、
     car: リストの第一要素を取り出す。
     cdr: リストの第一要素を除いたリストを返す。
     cons: リストの合成を行う。(cons 1 '(2 3 4))などの形で用いる。この例では(1 2 3 4)を返す。
     reverse: リストを非破壊的に逆順にする。
     nreverse: リストを破壊的に逆順にする。
     dolist: リストの要素を順にとる。(dolist (x '(1 2 3 4)) <処理> )などの形で用いる。
     mapcar: リストの要素に対し、それぞれ関数を適用する。(mapcar #'car '((1 2) (2 3)))のような形で用いる。pythonでは同様の関数としてmapが存在する。
     reduce: 二つの引数をとる関数を利用して、リストの要素に対して前から順に畳み込みをする。
     mapcan(Emacs Lispでは cl-reduce, cl-mapcan): 引数のリストに対して関数が返した要素のみから新たなリストを作る。pythonではfilterと呼ばれる。

 全然まとめ終わらなくて非常につらいです。