'(A. B) gerçekten bir liste midir?


15

.Gösterimle gerçekten kafam karıştı . Mı '(a . b)bir liste?

(listp '(a . b))döner tancak uzunluğunu bilmek istediğimde (length '(a . b))bir hata veriyor Wrong type argument: listp, b. Aynı şey, nth,mapcarvb. Gibi diğer işlevler için de aynı hatayı verir.

Ben ayırt edebilir bir fonksiyon var mıdır '(a b)ve '(a . b)?


Bağlam: özyinelemeli sürümünü uygulamak istediğimde bu sorunla karşılaştım mapcar. İşte benim uygulama

(defun true-listp (object)
"Return non-`nil' if OBJECT is a true list."
(and (listp object)  (null (cdr (last object)))))

(defun recursive-mapcar (func list)
"Evaluates func on elements of the list, then on elements of elements  of the list and so forth." 
(let ((output nil))
(flet ((comp (a b) nil)
       (call-fun-and-save (x) (add-to-list 'output (funcall func x) t 'comp))
       (recursion (l)
                  (mapcar
                   (lambda (x)
                     (call-fun-and-save x)
                     (if (and (true-listp x))  ;; HERE I use true-listp, testing for list or cons is not sufficient
                         (recursion x)))
                    l)))
   (recursion list))
  output))

Ayrıştırılmış html tüm özel etiketleri ayıklamak için bunu kullanın. htmlAyrıştırma örneği

;; buffer 'html'
<html>
<body>
<table style="width:100%">
  <tr>  <td>Jill</td>  <td>Smith</td>  <td>50</td> </tr>
  <tr>  <td>Eve</td>   <td>Jackson</td>   <td>94</td> </tr>
</table>
</body>
</html>

Sonra bütün ayıklamak <td>olarak

(with-current-buffer (get-buffer "html")
  (let ((data (libxml-parse-html-region (point-max) (point-min))))

    ;; gat only <td> tags
    (-non-nil
     (recursive-mapcar
      (lambda(x) (and (consp x) (equal 'td (car x)) x))
      data))
    data
    )
  )

1
true-list-pElisp'de hayır yoktur , çünkü bunu sağlamak için yeterince yararlı bulunmamıştır. Gerçekten, bir listenin uygun olup olmadığını en son test etmek istediğimi hatırlamıyorum, belki de kullanım durumunuz hakkında bize biraz daha bilgi verirseniz, sorununuzu başka bir şekilde çözmenize yardımcı olabiliriz.
Stefan

@Stefan Kısacası, özyinelemeli mapcar uygulamak istiyorum, verilen bir fonksiyonun belirli bir listenin elemanları üzerinde, daha sonra listenin elemanlarının elemanları üzerinde, daha sonra listenin elemanlarının elemanlarının elemanları üzerinde değerlendiririm. Bu yüzden bir öğenin gerçek bir liste olup olmadığını bilmem gerekir.
tom

Örneğin html ile ayrıştırdığımda libxml-parse-html-regionve tüm <td>etiketleri ayıklamak istediğimde kullanışlıdır .
tom

Bize uygun bir liste, uygun olmayan bir liste veya başka bir şey alabileceğiniz ve 3 vakayı farklı bir şekilde ele almanız gereken somut bir örnek gösterebilir misiniz? Çoğu durumda uğraşmak zorunda kaldım, "uygun" ve "uygunsuz" vakalar, gerçek uygunsuz kuyruğa ulaşana kadar paylaşılabilir, bu yüzden tekrar doğru olup olmadığını test etmeniz gerekmez: sadece bunun conspyerine.
Stefan

1
libxml sadece liste listelerini döndürmez. Bir XML öğesini temsil eden her liste forma (sembol nitelikleri. İçindekiler) sahiptir. Dolayısıyla, kodunuz mapcar'ı listelerin tüm öğelerine, yalnızca listenin üzerine tekrar tekrar uygulamamalıdır cddr(öğe adını ve niteliklerini atlamak için). Bunu yaptıktan sonra, tüm listelerin uygun olduğunu ve probleminizin kaybolacağını bulmalısınız. Ayrıca, kodunuzdaki tdbir tdöğenin özniteliğini karıştırabileceğiniz bir hatayı da düzeltir .
Stefan

Yanıtlar:


22

Bu tatmin edici listp, bu yüzden bir liste. bir yandan bir şeyin listpeksileri mi, yoksa nil(aka ()) mı, yoksa diğer bir şeyin mi olduğunu test eder.

Bir doğru liste veya gerçek liste (noktalı liste veya dairesel bir liste değildir veya bir liste) bir şeydir listpve ayrıca sahip nilson cdr olarak. Yani bir listesini sunan XSise uygun olmadığını (cdr (last XS))olduğunu nil(ve buna öyle ayırt nasıl).

Bunu koymanın başka bir yolu da uygun bir listenin cdr olarak uygun bir listeye sahip olmasıdır . Bu veri tipi (doğru) yolu Liste yazılan dilde tanımlanmıştır. Genel ve özyinelemeli bir tür tanımıdır: Genel bölüm, boş olmayan liste yapıcısına (genellikle consBTW olarak adlandırılır ) ilk argümanın herhangi bir türde olabileceğini söyler . Özyinelemeli bölüm, ikinci argümanının tür (uygun) Liste örneğinin bir örneği olduğunu söyler .

Evet, belli bir kontrol listpkullanarak uygun bir listedir (cdr (last XS))olduğunu nil. Yaratığın cdrinin kendisinin uygun bir liste olup olmadığını kontrol etmek için, olup olmadığını görmek için cdr'i sonuna kadar aşağıya doğru kontrol etmelisiniz nil. İsterseniz, bunun için bir yüklem tanımlayabilirsiniz:

(defun true-listp (object)
  "Return non-`nil' if OBJECT is a true list."
  (and (listp object)  (null (cdr (last object)))))

Dairesel bir listenin sonu olmasa da, Emacs (Emacs 24 ile başlayan) lastdoğru kontrol etmek için yeterince akıllıdır , bu nedenle bu kod dairesel bir liste için bile çalışır (ancak yalnızca Emacs 24.1 ve sonraki sürümler için; önceki sürümler için "sonsuz" özyineleme elde edersiniz yığın taşmasına kadar).

lengthYalnızca uygun listelerde ve diğer dizilerde olduğu gibi işlevleri kullanabilirsiniz . Ayrıca bkz safe-length. Fonksiyon .

Elisp kılavuzuna bakın, Düğüm Hücreleri .

Gösterime gelince (a b), sadece sözdizimsel şeker içindir (a . (b . nil))- Elisp kılavuzuna bakın, düğüm Noktalı Çifti Gösterimi


Uygun listeyi kontrol etmek için en iyi uygulama hangisidir? Olmadığını kontrol etme (cdr (last XS))olduğunu nilcrumblesome olduğunu. Gibi bir işlev yok proper-list-pmu?
tom

@tom: Bu ya da eşdeğeri bir şey gerekli - son eksilerini kontrol etmelisiniz. Şimdi bu konuya daha fazlasını ekledim.
Drew

@Çizim Fonksiyonun gövdesini olarak değiştiririm. (unless (atom x) (not (cdr (last x))))Böylece arayabilir (true-list-p "text")ve nilhata alamazsınız.
tom

@tom: Doğru; Teşekkür. Aslında, eksileri veya nil(yani listp) olduğundan emin olmak için önce test edilmelidir . (Ayrıca FWIW, ben kullanmıyorum unlessya whenda dönüş değeri için kullandığım. and, orVe ifbunun için.)
Drew
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.