Bir fonksiyondan keyfi bir noktada nasıl dönersiniz?


12

Bir işlev sona ermeden önce nasıl erken dönersiniz? Örneğin:

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

Yanıtlar:


19

Kullanabileceğimiz birkaç seçenek var.

Atmak

İşlevden çıkmak için catch/ throwdüğmelerine basabilirsiniz .

misal:

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

Blok

Ayrıca kullanabilir blockve return-from(size gereken etmek gerekir ancak cl-macs)

misal:

(require 'cl-macs)

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

cl-defun

Ayrıca , işlevle aynı ada cl-defunsahip bir örtük blockvar, böylece blockstili daha az ile yapabiliriz .

misal:

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

defun *

cl-defunayrıca defun*şu şekilde tanımlanan bir takma ad olarak da kullanılabilir 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 sözdizimi için bir tercihiniz yoksa, catch/ throwyakalama / atma açısından diğer yaklaşımlar uygulandığından, elisp'de / daha deyimseldir. Elisp manuel diyor: "Common Lisp dahil Lisp çoğu başka sürümleri, sırasız denetim transferini birkaç yolu vardır: return, return-from, ve go. Örneğin, Emacs Lisp sadece sahiptir throw."
phils

5

@EmacsFodder'ın kapsadığına ek olarak, sadece bir hata oluşturun.

Bu, kod, ignore-errorsveya gibi hata işleme yapılarının kapsamı içinde (dinamik olarak, sözcük olarak değil) çağrıldığında yardımcı olmaz condition-case, ancak aksi takdirde bir işlevden çıkmak için iyi bir yoldur. Aslında çoğu zaman yapılan budur.

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

Hatayı kendiniz ele almak istiyorsanız, arama kodunu (örneğin, nihayetinde çağıran my-funcbir şeye çağrı ) a condition-case. Yine, çoğu zaman, en az catch+ kullanmak kadar sık ​​yapılan budur throw. Her şey istediğiniz davranışa bağlıdır.


Yanıt için teşekkürler Drew, bunun oldukça yaygın bir yöntem olduğunu kabul ediyorum. Ancak, diğer birçok dilde erken bir dönüş yapmak , bir hatayla uğraşmak zorunda kalmanın karmaşıklığına neden olmaz . Soru / cevap setini araştırırken. Özellikle her zaman bana kludgy hissediyor "hata" tarzı alternatifler arıyordu. Bunu soru metninde açıkça belirtmedim.
ocodo

1
Her şey ne yapmak istediğinize bağlı. Hemen bitirmek istiyorsanız, daha fazla işlem / işlem yapmadan, bir hatayı yükseltmek Emacs'ta yerel olmayan bir çıkış için iyi bir yoldur. Eğer, yani yerel olmayan bir çıkışa sırasında bir şey yapmak istiyorsanız, o zaman, bir şekilde idare catch, unwind-protect, condition-caseve benzeri yararlıdır. Elisp kılavuzunun yerel olmayan çıkışlara ayrılmış bir bölümü vardır . (Ve hiçbiri hakkında özellikle kludgy yok, IMO.)
Drew

"Hissedilen" elbette tamamen özneldir. Yerel olmayan manuel referans için teşekkürler.
ocodo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.