2016-07-03 5 views
1

개체가 함수인지 (익명인지 여부)를 확인하는 안전한 방법을 확인하려고합니다. 분명히 그것은 여러 유형의 객체와 함께 작동elisp : 개체가 함수인지 테스트

(defun function-check (x) 
    (and (boundp 'x) 
     (if (symbolp x) (fboundp x) 
    (functionp x)))) 

: functionp 또는 fboundp으로
내가 오류를주는 예상대로, 내가 함께 노력하고 작동하지 않습니다 어쨌든

(setq lfun (lambda() "hello")) 
(function-check lfun) ; -> t 
(setq nfun 'buffer-name) 
(function-check nfun) ; -> t 
(setq slfun '(lambda() "hello")) 
(function-check slfun) ; -> t 

(function-check 'not-bound) ; -> safe nil 

, 내 코드를 찾고 그것을 그렇게 단순한 작업을하기에는 너무 장황하고 복잡한 것처럼 보입니다.
더 나아질 수 있습니까?

업데이트 :

요청으로

, 나는 "나는 예상대로 functionp, fboundp 지금 작동합니까"로 무슨 뜻인지 명확히.

유효한 후크를 감지한다고 가정 해 보겠습니다. 이 작동하지 않습니다

(setq var 'buffer-name) 
(functionp 'var)   ;nil 
(fboundp 'var)   ;nil 

우리는 사용할 필요가 :

(functionp var)   ;t 
(fboundp var)   ;t 

를이 우리가 var가 무효가 아닌지 확인해야 작동하지만, 그렇지 않으면 우리가 얻을 오류 :

(functionp void-var)  ;Lisp-error 
(fboundp void-var)  ;Lisp-error 

상황에 따라 추가 제어 코드 추가, 코드 컴파일 등을 의미합니다.

유효한 후크는 호출 가능한 모든 객체 일 수 있습니다 : 매크로, 함수, 람다는 유효한 후크입니다. 어쨌든 functionp 매크로 작동하지 않습니다 : 람다 식으로 작동하지 않습니다

(defmacro mac() "hello") 
(functionp 'mac) ;nil 

fbound 동안 :

(functionp '(lambda() t)) ;t 
(functionp (lambda() t)) ;t 
(fboundp '(lambda() t)) ;Lisp error 
(fboundp (lambda() t)) ;Lisp error 

이것은 또한 발생하면 변수에 식을 할당 :

(setq var '(lambda() t)) 
(functionp var)  ;t 
(fboundp var)  ;Lisp error 

하는 var이 기호 인 경우 테스트가 필요할 수 있습니다.

내가 이해하는 것처럼, 객체를 호출 할 수있는 직접적인 방법은 없다. 그러므로 내 시도이다.

+1

필자는 elisp를 손쉽게 사용할 수는 없지만, 이것은 끔찍한 버그처럼 보입니다. 아마도 ((또는 (functionp x) (및 (symbolp x) (fboundp x)))''를 원할 것입니다. quote'x'. 그렇다 할지라도'(funcall (lambda ....) ...)'이 elisp에서 작동하는지,'functionp'에서 그런 목록에 대해 말하는지를 잊어 버린다. – tfb

+3

'functionp'의 문제점은 무엇입니까? 그것은 객체가 함수인지 여부를 테스트하는 함수입니다. 어떤 오류가 발생 했습니까? 'functionp'와 같은 정의를 사용하지 않는다면 어떻게 "object is a function"을 정의 할 수 있습니까? – Gilles

+0

@Gilles 저는 여러분이 말하는 것처럼'functionp'는 아마도 대답이라고 생각합니다 : 그것은 elisp에서'(functionp 'car)'가 true 인 것처럼 보입니다 : Common Lisp에서는 false입니다. – tfb

답변

3

(boundp 'x) 수표는 여기 약간 동어 반복입니다. 동적 바인딩을 사용하여 코드를 컴파일하는 경우 (boundp 'x)t입니다. x은 함수를 입력 할 때 바인딩되기 때문에 항상 사용됩니다. 어휘 바인딩을 사용하여 코드를 컴파일하는 경우 x이라는 "전역"변수를 만들지 않는 한 (boundp 'x)은 아마도 nil입니다. 두 경우 모두 결과는 함수에 전달한 인수에 따라 다릅니다.

그래서 난 그냥이 필요하다고 생각 :

입니다
(defun function-check (x) 
    (if (symbolp x) 
     (fboundp x) 
    (functionp x))) 

, x 바인딩 기능을 가진 심볼, 또는 람다 함수 중 하나입니다 있는지 확인합니다.

+3

이것은'functionp'보다 어떻게 열등하지 않습니까? 함수는 함수로 실행 가능하지 않은 함수 바인딩을 가진 심볼에 대해't'를 반환합니다. 심볼을 전달할 때,'fboundp'는 함수 바인딩이 함수인지 정확하게 체크합니다. – Gilles

0

AUCTeX 패키지에서 사용 된 함수 술어의 흥미로운 예제를 발견했습니다.

(defun TeX-function-p (arg) 
    "Return non-nil if ARG is callable as a function." 
    (or (and (fboundp 'byte-code-function-p) 
     (byte-code-function-p arg)) 
     (and (listp arg) 
     (eq (car arg) 'lambda)) 
     (and (symbolp arg) 
     (fboundp arg)))) 

이 테스트 alist TeX-expand-list를 파싱하여 얻은 텍 명령어 (성분)을 호출하기 전에 AUCTeX 사용된다. TeX-expand-list이 거대하고 사용자 정의로,

(apply expansion arguments) 

TeX-function-p 철저한이며, 확장은 문자없는 오브젝트이 발생할 수 있습니다 다음 alist에서 발견 확장 함수 인 경우
는 다음을 호출합니다 또는 바인딩되지 않은 기호.

이 함수는 functionp이 호출 가능 객체를 테스트하는 데 항상 충분하지 않을 수도 있음을 보여줌으로써 내 질문에 대답합니다.

+0

'functionp'의 어떤 부분이 이미 처리되지 않았습니까? 'TeX-function-p '가 쓰여졌을 때 필요했을 수도 있지만 지금은 나에게 쓸데없는 것처럼 보입니다. – phils

+0

@phils : 조금 더 조사한 후에, 나는 [버그 리포트] (http://lists.gnu.org/archive/html/bug-gnu-emacs/2016-08/msg00537.html)를 조사했습니다. 뉴스가 도착하면 이에 따라이 게시물을 편집 할 것입니다. – antonio