[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
この章では、前の章で学んだことを基礎により複雑な関数を見ていくことにする。
copy-to-buffer
関数は、一つの定義の中で save-excursion
を
二回使う方法を示してくれる。一方、insert-buffer
関数の方は
interactive
式の中での * の使い方と、or
の使い方、
そして、オブジェクトの名前と、その名前のついたオブジェクトとの違いについ
て教えてくれる。
て
5.1 copy-to-buffer
の定義set-buffer
とget-buffer-create
を利用5.2 insert-buffer
の定義書き込み不可 と or
の使い方5.3 beginning-of-buffer
の完全な定義goto-char
,point-min
, そしpush-mark
を見てみる
5.4 復習 5.5 &optional
引数の練習問題&optional の練習問題
copy-to-buffer
の定義
append-to-buffer
がどのように動作するかを理解した後であれば、
copy-to-buffer
の方も簡単に理解出来る。この関数はテキストを他のバッ
ファにコピーする。ただし、そのバッファに付け加えるのではなく、以前あった
テキストを置き換えてしまう。copy-to-buffer
関数のコードは
append-to-buffer
のコードとほぼ同じであるが、erase-buffer
を使い、また save-excursion
を二回使っている点が違う。
(append-to-buffer
の説明については append-to-buffer
の定義, を参照。)
copy-to-buffer
の本体は次の通りである。
... (interactive "BCopy to buffer: \nr") (let ((oldbuf (current-buffer))) (save-excursion (set-buffer (get-buffer-create buffer)) (erase-buffer) (save-excursion (insert-buffer-substring oldbuf start end))))) |
このコードは append-to-buffer
とそっくりである。
append-to-buffer
の定義との違いが現れるのは、テキストがコピーされ
るバッファに移ってからである。つまり、この後 copy-to-buffer
関数
では以前の内容を消去してしまう。(これが、「置き換え」と言った意味である。
Emacs ではテキストを置き換える場合、以前の内容をまず消去し、次に新しいテ
キストを挿入する。) 以前の内容を消去した後、もう一度
save-excursion
が使われる。そして新しいテキストが挿入される。
何故 save-excursion
が二回も使われるのか? それを理解するために、
もう一度この関数が何をやっているか見てみよう。
大ざっぱには、copy-to-buffer
の本体は次のようになっている。
(let ( |
最初の save-excursion
は Emacs にテキストのコピー元のバッファを返
している。これは当たり前のことで、append-to-buffer
でも同じような
使われ方をしていたのだった。では何故二番目が必要なのか? 理由は、
insert-buffer-substring
が常にポイントを挿入されたリージョンの
最後に移動してしまうからである。二番目の save-excursion
があるおかげで、Emacs は挿入されたテキストの最初の位置にポイントを移動す
る。大抵の状況では、ユーザーは挿入されたテキストの最初の位置にポイントが
あるほうを好むものである。(勿論、copy-to-buffer
関数は終了時に元
居たバッファに戻る---しかし、もしユーザが次にコピー先のバッファに
移ったとすると、ポイントはそのテキストの先頭に移動してくれるというわけで
ある。このように、二番目の save-excursion
はちょっぴり気の効いた
働きをしてくれるものなのだ。)
insert-buffer
の定義
insert-buffer
もまた、バッファに関する関数である。このコマンドは
他のバッファをカレントバッファの中に挿入する。これは
append-to-buffer
や copy-to-buffer
と逆である。これらの方
は、カレントバッファからリージョンを取り出して他のバッファにコピー
するのであった。
更に、このコードは read-only なバッファに関する interactive
の使い方や、オブジェクトの名前と、その名前のついたオブジェクトそのものと
の違いの重要性を理解させてくれる。これがそのコードである。
(defun insert-buffer (buffer) "Insert after point the contents of BUFFER. Puts mark after the inserted text. BUFFER may be a buffer or a buffer name." (interactive "*bInsert buffer: ") (or (bufferp buffer) (setq buffer (get-buffer buffer))) (let (start end newmark) (save-excursion (save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) (insert-buffer-substring buffer start end) (setq newmark (point))) (push-mark newmark))) |
他の関数定義と同様に、テンプレートを使ってこの関数のアウトラインを見るこ とが出来る。
(defun insert-buffer (buffer) "説明文字列..." (interactive "*bInsert buffer: ") 本体...) |
5.2.1 insert-buffer
の中のインタラクティブ式書き込み不可の状態の時の動作 5.2.2 関数 insert-buffer
の本体部分本体には or
とlet
がある5.2.3 or
の代わりにif
を使ったinsert-buffer
or
の代わりにif
を使う5.2.4 本体部分の or
5.2.5 insert-buffer
の中のlet
式二つの save-excursion
式
insert-buffer
の中のインタラクティブ式
insert-buffer
ではインタラクティブ宣言の引数には二つの部分がある。
一つはアスタリスク `*' であり、もう一つは `bInsert buffer: '
である。
書き込み不可のバッファ インタラクティブ式の中の `b'
アスタリスクはバッファが read-only---つまり変更出来ないバッファである場合
のためのものである。もし、insert-buffer
が read-only なバッファで呼
ばれた場合、エコー領域にその旨を知らせるメッセージが表示され、ビープ音が
鳴るか、画面が明滅する。「あなたはこのバッファに如何なるものも挿入しては
いけませんよ」というわけである。アスタリスクの後には、次の引数と分離するた
めに改行コードを付ける必要はない。
インタラクティブ式の次の引数は小文字の `b' から始まっている。(これ
は append-to-buffer
のコードの中のとは違うことに注意。こっちでは
大文字の `B' を使っていたのだった。append-to-buffer
の定義, 参照。)
小文字の `b' は Lisp インタプリタに insert-buffer
の引数が存
在するバッファないしは、その名前でなければならないことを示している。(大
文字の `B' オプションの方は存在しないバッファであっても良い。)
Emacs はプロンプトを出してバッファの名前を要求し、同時にデフォルトのバッ
ファも提示してくれる。名前の補完もやってくれる。もし、ここで存在しないバッ
ファを指定すると、"No match" というメッセージを受け取る。端末によって
はビープ音がするかもしれない。
insert-buffer
の本体部分
関数 insert-buffer
の本体は、主に二つの部分からなっている。一つは
or
式であり、もう一つは let
式である。or
式を使う目
的は、引数 buffer
がバッファの名前ではなくちゃんとバッファそのも
のにバインドされていることを確認することである。let
式の本体は、
他のバッファをカレントバッファに挿入するコードを含んでいる。
大まかに言って、二つのS式は次のように insert-buffer
関数の中に組
み込まれている。
(defun insert-buffer (buffer)
"説明文字列..."
(interactive "*bInsert buffer: ")
(or ...
...
(let (変数リスト)
|
引数 buffer
がバッファの名前ではなくバッファそのものにバインドさ
れているかを or
式がどのようにして確かめているかを理解するには、
最初に関数 or
を理解する必要がある。
が、その前にまずこの部分を if
を使って書き直してみたい。そうすれ
ばより身近な方法で何がなされているかを見ることが出来るだろう。
or
の代わりに if
を使った insert-buffer
やるべき仕事は buffer
の値がバッファそのものであり、バッファ名で
はないことを確認することである。もし値が名前であったら、その名前のついた
バッファを持ってこないといけない。
まずあなたが何かのコンファレンスに参加しており、案内係があなた方の名前が 書かれたリストをもってあなたを探している状況を思い浮かべて欲しい。この状 態では案内係はあなた自身ではなく、あなたの名前に「バインド」されている。 しかし、案内係があなたを見つけてあなたの腕を取った時点で、案内係はあなた 自身に「バインド」されたことになる。
Lisp ではこの状況を次のように説明出来る。
(if (not (お客をつかまえている)) (お客を見つけて腕を取る)) |
我々はこれと同じことをバッファについてやりたいわけである---バッファそのも のでない場合も、バッファを見つけて取って来たいのだ。
bufferp
という(バッファの名前ではなく)バッファかどうかを判定して
くれる述語を使うと、このコードを次のように書くことが出来る。
(if (not (bufferp buffer)) ; if-part (setq buffer (get-buffer buffer))) ; then-part |
コメントにもあるが、上の式で、if
式の真偽テストの部分は
(not (bufferp buffer))
であり、一方 then-part の部分は
(setq buffer (get-buffer buffer))
である。
このテストの中では bufferp
関数は引数がバッファであれば真の値を返
す---しかしバッファの名前であれば偽の値を返す。(bufferp
という関
数の名前の最後は `p' で終わっている。以前見たようにこの `p' は、
この関数が述語、つまり、ある性質を持つか否かを判定する関数であることを示
すための工夫として付けられている。
関数に間違った型の引数を与えると, を参照
のこと。)
(bufferp buffer)
式の前には関数 not
がある。即ち
真偽テストは次の通りである。
(not (bufferp buffer)) |
not
は引数が偽であれば真を返し、偽であれば真を返す関数である。従っ
て、もし (bufferp buffer)
が真を返せば、not
式が偽を返すし、
偽を返せば真を返す。「真でない」というのは偽ということだし、「偽でない」
というのは真だというわけである。
if
は、このテストを使って次のように動作する。変数 buffer
の値がバッファの名前ではなく実際にバッファだった場合、真偽テストの結果
は偽である。すると、if
式は then-part を評価しない。これはまとも
な動作である。というのは、もし変数 buffer
が本当にバッファであれ
ば、これに対して特に何もする必要はないからである。
一方で、buffer
の値がもしバッファそのものではなくバッファの名前で
あったとすると、真偽テストでは真が返り、結果として then-part が評価される。
今の場合、then-part は (setq buffer (get-buffer buffer))
である。
このS式は、その名前のついた実際のバッファを得るために get-buffer
関数を使っている。そして、setq
で、変数 buffer
の値をバッ
ファの名前から実際のバッファそのものに置き換えている。
or
insert-buffer
関数で or
式を使う目的は引数 buffer
がバッファの名前ではなくバッファそのものにバインドされているかどうかを確
認することにある。前節で、どのようにして if
を使ってこの作業をす
るかを見た。しかし、insert-buffer
関数では実際は or
を使っ
ている。この理由を理解するには、or
関数の働きを理解しなければなら
ない。
関数 or
はいくらでも引数を持つことが出来る。この関数は各引数を順に
評価していき、nil
でなかった最初の引数の値を返す。また、これが
or
の重要な特徴なのだが、この関数は引数で nil
以外の値を返
すものがあった場合、その後の引数はもはや評価しない。
今の場合の or
式は次の通りである。
(or (bufferp buffer) (setq buffer (get-buffer buffer))) |
or
の最初の引数は S式 (bufferp buffer)
である。この式は、
もし buffer がバッファそのものでありバッファの名前ではない場合は、真を返
す。or
式では、この場合、or
式の値として真を返し、その後の
引数は評価されない---我々にはこの方が都合が良い。というのもこの場合には
つまり buffer
が真のバッファである場合には、この値について何もす
る必要がないからである。
一方で、もし (bufferp buffer)
が nil
であれば、それは
buffer
の値がバッファの名前であるということである。この場合、Lisp
インタプリタは or
式の次の引数も評価する。これは (setq
buffer (get-buffer buffer))
という式である。この式は
nil
でない値を返す。これが変数 buffer
にセット
された値である---そしてこの値はバッファそのものであり、バッファの名前ではない。
以上のことから、シンボル buffer
は常に、あるバッファの名前ではな
くバッファそのものにバインドされることになる。また、以上の手続きは全てが
必要なことである。というのも、次の行の set-buffer
関数はバッファ
に対してしか働かないからである。
ついでだが、or
を使った場合、案内係というのは次のように書ける。
(or (お客をつかまえている) (お客を見つけて腕を取る)) |
insert-buffer
の中の let
式
insert-buffer
関数では、変数 buffer
がバッファの名前ではな
くバッファそのものを表わすことを確認した後には、 let
式が続く。
ここでは三つの変数 start
, end
, newmark
を指定してい
る。これらの変数は let
式の内部でのみ使われ、let
式の評価
が終わるまでの間は、一次的に Emacs 内の同じ名前の他の変数は隠されている。
let
式の本体は二つの save-excursion
を使っている。まずは、
内側にある方の save-excursion
式を細かく見ていこう。この式は次の
通りである。
(save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) |
S式 (set-buffer buffer)
は、Emacs が注目するバッファをテキストが
コピー元のバッファに切り替える。このバッファの中で、point-min
コ
マンド及び、point-max
コマンドを使って変数 start
と 変数
end
に各々バッファの始まりと終わりの位置を設定する。setq
を使って、一つのS式で二つの変数を同時に設定する方法についてはもう既に説
明したのだった。setq
の最初の引数は二番目の値に、三番目の引数は四
番目の引数の値にセットされる。
外側の save-excursion
式は次の通りである。
(save-excursion (内側の |
関数 insert-buffer-substring
は buffer
から、その中
のstart
と end
で指定されたリージョン内のテキストを、カレ
ントバッファの中にコピーする。今の場合、コピー元のバッファ全体が
start
と end
の間にあるために、そのバッファ全体が現在編集
中のバッファにコピーされることになる。次に、この時点で挿入されたテキスト
の最後にあるポイントの値が、変数 newmark
に記録される。
外側の save-excursion
の本体が評価された後、ポイントとマークの位
置は元の位置に戻される。
しかしながら、ポイントとマークの位置は新しく挿入されたテキストの最初と最
後にある方が、何かと都合が良い。newmark
変数は挿入されたテキスト
の最後の位置を記録する。let
式の最後の行で (push-mark
newmark)
というS式でマークをこの位置に設定している。(以前のマークの位
置に移動することも可能である。この値はマークリングに保存されていて、
C-u C-SPC で遡ることが出来る。) 一方、ポイントの方は初めから
挿入されたテキストの最初の位置にある。これは insert
関数を呼び出
す前のポイントの位置がここだからである。
完全な let
式は次の通りである。
(let (start end newmark) (save-excursion (save-excursion (set-buffer buffer) (setq start (point-min) end (point-max))) (insert-buffer-substring buffer start end) (setq newmark (point))) (push-mark newmark)) |
append-to-buffer
関数の時と同じように、insert-buffer
関数
も let
, save-excursion
, そして set-buffer
を使って
いる。それに加えて、この関数は or
の使い方の一つも教えてくれてい
る。これらの関数は皆大切な部品であり、これから何度でも出てくることだろう。
beginning-of-buffer
の完全な定義
beginning-of-buffer
関数の基本的な構造については、既に議論したこ
とがあるのだった。(簡略版 beginning-of-buffer
の定義.) このセクションではこの定義の複雑な
部分を説明することにする。
以前説明した通り、引数無しで beginning-of-buffer
を呼び出すと、そ
の時点でのポイントの位置にマークを設定して、カーソルがバッファの先頭に移
動する。しかしながら、もしこのコマンドが1から10までの数と一緒に呼び出さ
れた場合、この関数はバッファ全体を10としてこの数の割合の分を計算し、バッ
ファの先頭からその割合の分だけ進んだ位置にカーソルを移動させる。というわ
けで、M-< でこのコマンドを呼び出せば、カーソルはバッファの先頭に移
動するし、もし例えば C-u 7 M-< として呼び出せば、カーソルはバッファ
全体の70%分の位置にポイントを移動する。もし引数が10より大きかった場合は
バッファの最後に位置に移動する。
beginning-of-buffer
関数は、引数無しで呼び出すことが出来る。つま
り、引数は省略可能である。
5.3.1 省略可能な引数 5.3.2 引数付きで呼び出された場合の beginning-of-buffer
省略可能引数の例 5.3.3 完全版 beginning-of-buffer
完全版
特にそうでないと言われない限り、Lisp は、関数定義で引数が指定された関数 はその引数のための値とともに呼ばれるものと思っている。もし、そうでなかっ た場合、エラーが出され、`Wrong number of arguments' というメッセー ジを受け取ることになる。
しかしながら、Lisp の特徴として省略可能引数というものがある。ある
キーワード (keyword) を使うと Lisp インタプリタにその引数が
省略可能だと伝えることが出来るのだ。そのキーワードとは &optional
で
ある。(`optional' の前の `&' もこのキーワードの一部分である。)
関数定義の中でこのキーワード &optional
の後に続く引数は、関数が呼
ばれる際に必ずしも値を渡される必要はない。
というわけで、beginning-of-buffer
の関数定義の最初の行は次のように
なる。
(defun beginning-of-buffer (&optional arg) |
また、関数定義全体のアウトラインは次のようになっている。
(defun beginning-of-buffer (&optional arg) "説明文字列..." (interactive "P") (push-mark) (goto-char (もし引数があれば どこへ行けばよいか調べる そうでなければ次の場所に (point-min)))) |
この関数は simplified-beginning-of-buffer
と似ている。違うのは、
interactive
式に "P"
が引数として使われていることと、
引数が指定されている場合にカーソルを何処に移動するかを判断する
goto-char
関数に続いて if-then-else 式が来ていることである。
interactive
式の中の "P"
は、Emacs に、関数に前置
引数を渡すように伝えるものである。前置引数というのは
META キーに続いて数をタイプするか、C-u に押してから数をタイ
プすることで作ることが出来る。(もし C-u に続いて数を入力しない場合
には、デフォルトとして4が渡される。)
if
式の真偽テストの部分は単純である。単に arg
だけだ。もし、
arg
が nil
以外の値を持てば、即ち
beginning-of-buffer
が引数付きで呼ばれた場合は、真偽テストでは
真が返り、if
式の then-part が評価される。一方、もし
beginning-of-buffer
が引数とともに呼ばれなかったなら、arg
の値は nil
になり、if
式の else-part の方が評価される。
else-part は単に point-min
であり、この場合には
goto-char
式の全体は (goto-char (point-min))
になる。
これは、以前の短縮版 beginning-of-buffer
関数で見た通りである。
beginning-of-buffer
beginning-of-buffer
が引数付きで呼び出された場合は、
goto-char
に渡す値を計算する、あるS式が評価される。このS式は、
ちょっと見にはかなり複雑に見える。内部に if
式を含んでいるし、算
数を沢山使っている。実際のコードは次の通りである。
(if (> (buffer-size) 10000) ;; バッファサイズが大きい場合のオーバーフローを避ける! (* (prefix-numeric-value arg) (/ (buffer-size) 10)) (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
しかし、他の複雑そうなS式と同様に、これもテンプレートに当てはめてみれば 理解しやすくなる。この場合は、if-then-else 式のテンプレートに当てはめる。 骨組みは次のようになる。
(if (バッファが大きいなら バッファのサイズを10で割り引数を掛ける そうでなければ別の計算をする |
この中の if
式の真偽テストはバッファのサイズをチェックしている。
その理由は、Emacs Lisp の version 18 は約8,000,000以下の数値しか扱わない
のだが(そんなに大きな数は必要ない)、この計算に従うと、大きなバッファの場
合は Emacs は大き過ぎる数を扱うことになってしまうからだ。コードのコメン
トの中に出てくる「オーバーフロー」とは数が大き過ぎることを意味している。
ということで、バッファが大きい場合と、そうでない場合の二つに分けている。
大きなバッファの場合 小さなバッファの場合
beginning-of-buffer
の中で内側にある方の if
式はバッファの
サイズが10,000文字を越えているかどうかをテストしている。そのために、
>
と buffer-size
という関数を使っている。
その行は次の通りである。
(if (> (buffer-size) 10000) |
もしバッファが大きい場合は、if
式の then-part が評価される。この
部分を読みやすいよう書き直すと次のようになる。
(* (prefix-numeric-value arg) (/ (buffer-size) 10)) |
このS式は乗法であり、二つの引数を関数 *
に渡している。
最初の引数は (prefix-numeric-value arg)
である。
interactive
宣言で "P"
が指定されている場合、引数は関数に
「未処理の前置引数」(raw prefix argument) として渡され、数値としては渡さ
れない。(リストの中では数値である。) 算数で使えるようにするには変換する
必要があり、その仕事を prefix-numeric-value
がやっているのである。
二番目の引数は (/ (buffer-size) 10)
である。この式は数値としての
バッファの値を10で割る。これはバッファサイズの一割にどれだけの文字数が含
まれているかを計算するものだ。(Lisp では /
は除法に使われる。
*
が乗法に使われるのと同様である。)
乗法の式全体としては、この値に前置引数の値を掛けることになる---こんな感 じだ。
(* 数値としての前置引数 バッファの10分の1の文字数) |
(訳註:ここでの文字数とは勿論 ASCIIコードでの話で、日本語等の多バイト文 字が入ると話はまた違ってくる。)
例えば、仮に前置引数が `7' だったとするなら、この10分の1の数に7を掛 けることで、バッファの中の70%の位置が得られることになる。
結局、バッファが大きい場合の goto-char
式全体は次のようになる。
(goto-char (* (prefix-numeric-value arg) (/ (buffer-size) 10))) |
これでカーソルは望む場所に移動してくれる。
バッファが10,000文字よりも小さかった場合は、ちょっと違った計算方法が取ら れる。さっきの方法でも出来るのだから、こんなことをする必要はないと思うか もしれない。しかし、バッファが小さい場合、初めの方法ではカーソルを望む場 所にきちんと移動してくれない。次に説明する二番目の方法の方がちゃんとした 仕事をしてくれる。
コードは次の通りである。
(/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
このコードの中で何をしているかは、括弧の中にどのように関数が埋め込まれて いるかを見れば分る。各々の式をそれを含む括弧より深くインデントしてやれば、 より見やすくなる。
(/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) |
これらの括弧を見ると、もっとも内側にある関数は
(prefix-numeric-value arg)
であることが分る。これは未処理の
前置引数を数値に変換するものである。この数値は次の式によってバッファサイズと
掛け合わされる。
(* (buffer-size) (prefix-numeric-value arg) |
この掛け算では、バッファのサイズの値よりも大きな数が生ずる---例えば引数 が7なら7倍大きな数になる。これに10が加えられ、最後にこの大きな数が10で割 られる。こうして得られる値は、バッファのサイズ中の目的とする割合よりも一 文字分だけ大きな数である。
これら一連の操作の結果で得られた数が goto-char
に渡され、カーソル
がその位置に移動する。
beginning-of-buffer
ここで、beginning-of-buffer
の完全なコードを挙げておく。
(defun beginning-of-buffer (&optional arg) "Move point to the beginning of the buffer; leave mark at previous position. With arg N, put point N/10 of the way from the true beginning. Don't use this in Lisp programs! \(goto-char (point-min)) is faster and does not set the mark." (interactive "P") (push-mark) (goto-char (if arg (if (> (buffer-size) 10000) ;; 大きなバッファサイズの場合のオーバーフローを避ける! (* (prefix-numeric-value arg) (/ (buffer-size) 10)) (/ (+ 10 (* (buffer-size) (prefix-numeric-value arg))) 10)) (point-min))) (if arg (forward-line 1))) |
二つの細かな点を除けば、これまでの議論でこの関数がどう動くかが分るだろう。 細かな点の一つ目は、説明文字列についてであり、二つ目は、この関数の最後の 行に関するものである。
で、一点目だが、説明文字列の中に、あるS式についてのリファレンスがある。
\(goto-char (point-min)) |
この式の最初の括弧の前に `\' が使われている。この `\' は Lisp インタプリタに対し、このS式は説明として表示されるもので あって、S式として評価されるものではないことを示すものである。
次に二点目だが、beginning-of-buffer
コマンドの最後の行は、この関
数が引数とともに呼ばれた場合に、ポイントを次の行の最初に持ってくためのも
のである。
(if arg (forward-line 1))) |
これによって、カーソルはバッファの中の適当な割合の位置の次の行の先頭に移 動する。これが最良の位置であろう。カーソルは少くとも要求された割 合よりかは常に大きい位置に移動するからだ。この動作はちょっと几帳面過ぎる かもしれないが、かと言ってそうしなければ、必ず文句を言う人がいるだろう。
ここで、この章の幾つかのトピックを手短にまとめておく。
or
nil
でない最初の値を返す。ただし、もしど
の引数も nil
を返した場合は nil
を返す。一言で言うと、引数
の中で真である最初の値を返す。つまり、ある引数が真であるかまたは
(or) その他の引数のどれかが真であれば真の値を返す。
and
nil
があれば、nil
を返し、どれも nil
で無ければ最後の引数の値を返す。一言で言うと、
全ての引数が真である場合のみ真である値を返す。つまり、ある引数が真であり、
かつ (and) その他の引数も全て真である場合に真の引数を返す。
&optional
forward-line
erase-buffer
bufferp
t
を返す。そうでない場合は nil
を返す。
&optional
引数の練習問題
省略可能な引数を持ち、その引数の数が fill-column
の値よりも大きい
か小さいかをテストして結果を教えてくれるようなインタラクティブな関数を書
きなさい。ただし、引数なしの場合は56をデフォルトとして使うようにしなさい。
[ << ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |