Як ви повертаєтесь з функції у довільній точці?


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)))

Блок

Ви також можете використовувати blockі return-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є більш ідіоматичним в elisp, оскільки інші підходи в кінцевому рахунку реалізуються з точки зору лову / кидання. Elisp керівництво каже: «Більшість інших версій Lisp, включаючи Common Lisp, є кілька способів передачі управління nonsequentially: return, return-from, і go., Наприклад , Emacs Lisp має тільки throw
філ

5

Окрім того, що охоплювало @EmacsFodder, просто створіть помилку.

Це не допоможе, якщо код викликається (динамічно, не лексично) в межах конструкцій, що керують помилками, таких як ignore-errorsабо condition-case, але в іншому випадку це прекрасний спосіб вийти з функції. Це насправді те, що робиться більшість часу.

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

Якщо ви хочете впоратися з помилкою самостійно, тоді ви можете помістити код виклику (наприклад, дзвінок на щось, що остаточно дзвонить my-func) всередині condition-case. Знову ж таки, це робиться більшість часу, принаймні так часто, як використання catch+ throw. Все залежить від того, якої поведінки ви хочете.


Дякую за відповідь Дрю, я згоден, що це досить поширений метод. Однак виконання раннього повернення багатьма іншими мовами не спричиняє складності того, щоб потім боротися з помилкою. При дослідженні набору питань / відповідей. Я спеціально шукав альтернативи стилю "помиляються", який завжди відчуває мене неприємно. Я не зазначив цього прямо в тексті запитання.
окудо

1
Все залежить від того, що ви хочете зробити. Якщо ви хочете закінчитись негайно, без подальшої обробки / обробки, то підвищення помилки - це хороший спосіб піти на нелокальний вихід у Emacs. Якщо ви хочете зробити що - то під час нелокального виходу, тобто, обробляти його в деякому роді, то catch, unwind-protect, condition-caseі т.п. корисні. Є цілий розділ посібника Елісп, присвячений нелокальним виходам . (І нічого з цього немає, особливо IMO.)
Дрю

"Відчуває", безумовно, суб'єктивно. Дякую за нелокальний посібник ref.
ocodo
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.