« プログラミングを始めるには(31) | Main | プログラミングを始めるには(33) »

August 27, 2014

プログラミングを始めるには(32)

では今囘はお約束通りarglistinteractiveの關係について。lambda式におけるarglistのフルスペックは以下の通り。

(lambda (arg1 &optional arg2 &rest arg3)
  "docstring"
  body...)

上記のlambda式においては、arg1は必須パラメータであり、arg2arg3はオプショナルなパラメータとなる。そしてarg3はリストとして渡される。もちろん呼び出し側が渡さなかった場合は、どちらもnilになる。

((lambda (arg1 &optional arg2 &rest arg3)
   (print arg1)
   (print arg2)
   (print arg3)
   (if arg2
       (if arg3
	   (apply '+ arg1 arg2 arg3)
	 (+ arg1 arg2))
     arg1)) 1 2 3 4 5)
1
2
(3 4 5)
=>15

((lambda (arg1 &optional arg2 &rest arg3)
   (print arg1)
   (print arg2)
   (print arg3)
   (if arg2
       (if arg3
	   (apply '+ arg1 arg2 arg3)
	 (+ arg1 arg2))
     arg1)) 1 2)
1
2
nil
=>3

((lambda (arg1 &optional arg2 &rest arg3)
   (print arg1)
   (print arg2)
   (print arg3)
   (if arg2
       (if arg3
	   (apply '+ arg1 arg2 arg3)
	 (+ arg1 arg2))
     arg1)) 1)
1
nil
nil
=>1

arglistの說明はこれ以上でもこれ以下でもない、まさにこの通りである。applyはこのようなarglistをファンクションに適用するのに使用するビルトインファンクションである。さて、問題なのはinteractiveである。

interactive is a special form in `C source code'.
(interactive args)

Specify a way of parsing arguments for interactive use of a function.
For example, write
  (defun foo (arg) "Doc string" (interactive "p") ...use arg...)
to make ARG be the prefix argument when `foo' is called as a command.
The "call" to `interactive' is actually a declaration rather than a function;
 it tells `call-interactively' how to read arguments
 to pass to the function.
When actually called, `interactive' just returns nil.

The argument of `interactive' is usually a string containing a code letter
 followed by a prompt.  (Some code letters do not use I/O to get
 the argument and do not need prompts.)  To prompt for multiple arguments,
 give a code letter, its prompt, a newline, and another code letter, etc.
 Prompts are passed to format, and may use % escapes to print the
 arguments that have already been read.
If the argument is not a string, it is evaluated to get a list of
 arguments to pass to the function.
Just `(interactive)' means pass no args when calling interactively.

Code letters available are:
a -- Function name: symbol with a function definition.
b -- Name of existing buffer.
B -- Name of buffer, possibly nonexistent.
c -- Character (no input method is used).
C -- Command name: symbol with interactive function definition.
d -- Value of point as number.  Does not do I/O.
D -- Directory name.
e -- Parametrized event (i.e., one that's a list) that invoked this command.
     If used more than once, the Nth `e' returns the Nth parameterized event.
     This skips events that are integers or symbols.
f -- Existing file name.
F -- Possibly nonexistent file name.
G -- Possibly nonexistent file name, defaulting to just directory name.
i -- Ignored, i.e. always nil.  Does not do I/O.
k -- Key sequence (downcase the last event if needed to get a definition).
K -- Key sequence to be redefined (do not downcase the last event).
m -- Value of mark as number.  Does not do I/O.
M -- Any string.  Inherits the current input method.
n -- Number read using minibuffer.
N -- Numeric prefix arg, or if none, do like code `n'.
p -- Prefix arg converted to number.  Does not do I/O.
P -- Prefix arg in raw form.  Does not do I/O.
r -- Region: point and mark as 2 numeric args, smallest first.  Does no I/O.
s -- Any string.  Does not inherit the current input method.
S -- Any symbol.
U -- Mouse up event discarded by a previous k or K argument.
v -- Variable name: symbol that is user-variable-p.
x -- Lisp expression read but not evaluated.
X -- Lisp expression read and evaluated.
z -- Coding system.
Z -- Coding system, nil if no prefix arg.
In addition, if the string begins with `*'
 then an error is signaled if the buffer is read-only.
 This happens before reading any arguments.
If the string begins with `@', then Emacs searches the key sequence
 which invoked the command for its first mouse click (or any other
 event which specifies a window), and selects that window before
 reading any arguments.  You may use both `@' and `*'; they are
 processed in the order that they appear.

interactiveのヘルプを參照すると、上記のように長々と書かれている。知ったかぶりするとボロが出るので腹に落ちていることだけ書くと、必須パラメータとオプショナルパラメータだけなら、普通は上記の指示子を使用出來る。そうでない場合、たとえば候補を表示して入力を促したり、レストパラメータの場合は上記の指示子では入力出來ないので、そのパラメータを受け取る式を書かなければならないようだ。

(defun test-interactive-1 (a)
  (interactive "nnumber=")
  (print a))
=>test-interactive-1

(call-interactively 'test-interactive-1)
;;; ミニバッファから1を入力
1
=>1

(defun test-interactive-2 (a b)
  (interactive "na=\nnb=")
  (print a)
  (print b)
  (+ a b))
=>test-interactive-2

(call-interactively 'test-interactive-2)
;;; ミニバッファから1,2を入力
1
2
=>3

(defun test-interactive-3 (&rest nums)
  (interactive (mapcar 'string-to-number
		       (split-string (read-string "numbers=") " ")))
  (print nums)
  (apply '+ nums))
=>test-interactive-3

(call-interactively 'test-interactive-3)
;;; ミニバッファから"1 2 3 4 5"を入力
(1 2 3 4 5)
=>15

(defun test-interactive-4 (present)
  (interactive (list (completing-read "Please give me "
				      '("orange" "apple" "pear"))))
  (print present)
  (concat (if (string= "pear" present)
	      "I like "
	    "I don't like ")
	  present))
=>test-interactive-4

(call-interactively 'test-interactive-4)
;;; ミニバッファからorangeを補完入力
"orange"
=>"I don't like orange"

いきなりこうやって說明すると、ちょっとハードルが高いかもしれないが、これらの例を參考にエラーを出しながら自分で實行し、いろいろと確認してみると良い。

|

« プログラミングを始めるには(31) | Main | プログラミングを始めるには(33) »

Comments

Post a comment



(Not displayed with comment.)


Comments are moderated, and will not appear on this weblog until the author has approved them.



TrackBack

TrackBack URL for this entry:
http://app.cocolog-nifty.com/t/trackback/74224/60215271

Listed below are links to weblogs that reference プログラミングを始めるには(32):

« プログラミングを始めるには(31) | Main | プログラミングを始めるには(33) »