임의의 지점에서 함수에서 어떻게 돌아 옵니까?


12

함수가 끝나기 전에 어떻게 일찍 복귀합니까? 예를 들면 다음과 같습니다.

(defun my-func () 
 "for example."
 (unless something (return nil))
 ; continue as usual...
 (+ 42 1))

답변:


19

다양한 옵션이 있습니다.

던지다

당신은 수 catch/ throw기능을 종료합니다.

예:

(defun my-func ()
  "thrown error"
  (catch 'my-catch
    (when t
      (throw 'my-catch "always going to throw"))
    (+ 42 1)))

블록

당신은 또한 사용할 수 있습니다 blockreturn-from(당신이 필요로 할 필요가 있지만 cl-macs)

예:

(require 'cl-macs)

(defun my-func ()
  "block / return-from"
  (block my-func
    (when t
      (return-from my-func))
    (+ 42 1)))

cl-defun

우리는 또한이 cl-defun암시 가지고있는 block우리가 할 수 있도록 함수와 같은 이름을 가진 block적은 스타일.

예:

(require 'cl-macs)

(cl-defun my-func ()
  "cl-defun implicit block"
  (when t
    (return-from my-func)) ; my-func is an implicit block.
  (+ 42 1)))

즐거움 *

cl-defun다음과 같이 defun*정의 된 별칭으로도 사용할 수 있습니다 cl.el.

(require 'cl)

(defun* my-func ()
  "defun* implicit block"
  (when t
    (return-from my-func)) ; my-func is an implicit block.
  (+ 42 1)))

4
CL 구문을 선호하지 않는 경우 다른 접근법은 궁극적으로 catch / throw 측면에서 구현되므로 catch/ throw는 더 관용적입니다. elisp 매뉴얼은 말한다 : "CL의 포함 리스프의 대부분의 다른 버전, 비 순차적으로 제어를 전송하는 여러 가지 방법이 있습니다 return, return-from하고 go. 예를 들어, 이맥스 리스프는있다 throw."
phils

5

@EmacsFodder가 다루는 것 외에도 오류가 발생합니다.

코드가 ignore-errorsor 와 같은 오류 처리 구문의 범위 내에서 (동적으로, 어휘 적으로) 호출되지 않으면 도움이되지 condition-case않지만 그렇지 않으면 함수를 종료하는 좋은 방법입니다. 실제로 대부분의 시간이 수행됩니다.

(defun my-func () 
 "..."
 (unless something (error "Whoops!"))
 ; continue as usual...
 (+ 42 1))

오류를 직접 처리하려면 호출 코드 (예 : 울리게 호출하는 것에 대한 호출 my-func)를 안에 넣을 수 있습니다 condition-case. 다시 말하지만, 이것은 적어도 catch+ 를 사용하는 것만 큼 자주 수행됩니다 throw. 그것은 당신이 원하는 행동에 달려 있습니다.


답변 Drew에게 감사드립니다. 나는 이것이 일반적인 방법이라는 데 동의합니다. 그러나 다른 많은 언어로 조기에 복귀 한다고해서 오류를 처리해야하는 복잡성 이 발생하지는 않습니다 . 질문 / 응답 세트를 조사 할 때. 나는 항상 나에게 기분이 좋지 않은 "오류"스타일에 대한 대안을 찾고 있었다. 질문 텍스트에 명시 적으로 지정하지 않았습니다.
ocodo

1
그것은 모두 당신이하고 싶은 것에 달려 있습니다. 추가 처리 / 처리없이 즉시 종료하려면 Emacs에서 오류를 발생시키는 것이 로컬이 아닌 종료로가는 좋은 방법입니다. 당신은 즉, 로컬이 아닌 종료하는 동안 뭔가를 할 경우, 어떤 방법으로 그것을 처리 catch, unwind-protect, condition-case그리고처럼 유용하다. 비 로컬 이탈 에 대한 Elisp 매뉴얼의 전체 섹션 있습니다. (그리고 IMO에 대해서는 특별히 별다른 문제는 없습니다.)
Drew

"느낌"은 전적으로 주관적입니다. 로컬이 아닌 수동 참조에 감사드립니다.
ocodo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.