2017-06-01 51 views
1

我正在使用messenger api from facebook,使用ningle。有在我的計劃了一下,我需要這個ALIST從jonathan來上班:使用泛型序列系統與lisp共同lisp與alist來自jonathan

CL-USER> (defparameter *params* 
      '(("entry" 
       (("messaging" 
       (("message" ("text" . "hola") ("seq" . 3227) 
        ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
       ("timestamp" . 1496071517968) 
       ("recipient" ("id" . "474086316315717")) 
       ("sender" ("id" . "1695095647186162")))) 
       ("time" . 1496071518212) ("id" . "474086316315717"))) 
      ("object" . "page"))) 

*PARAMS* 
CL-USER> (length *params*) 
2 

然後,我有與入門部分工作:

CL-USER> (defparameter entries (cdr (assoc "entry" *params* :test #'string=))) 
ENTRIES 
CL-USER> entries 
((("messaging" 
    (("message" ("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
    ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
    ("sender" ("id" . "1695095647186162")))) 
    ("time" . 1496071518212) ("id" . "474086316315717"))) 
CL-USER> (length entries) 
1 

然後我定義了兩個函數工作與此:

(defun extract-entry (entry) 
    (let ((id (cdr (assoc "id" entry :test #'string=))) 
     (time (cdr (assoc "time" entry :test #'string=))) 
     (messaging (cdr (assoc "messaging" entry :test #'string=)))) 
    messaging)) 


(defun extract-messaging (event) 
    (let ((message (cdr (assoc "message" event :test #'string=)))) 
    message)) 

然後我操作:

CL-USER> (defparameter messaging (extract-entry (first entries))) 
MESSAGING 
CL-USER> messaging 
((("message" ("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
    ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
    ("sender" ("id" . "1695095647186162")))) 
CL-USER> (length messaging) 
1 


CL-USER> (defparameter message (extract-messaging (first messaging))) 
MESSAGE 
CL-USER> message 
(("text" . "hola") ("seq" . 3227) 
("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
CL-USER> (length message) 
3 

而且它工作得很好,那麼我想申請generic-sequences此部分:

CL-USER> (gen-seq:seq->list (gen-seq:seq-map #'extract-messaging messaging)) 
((("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u"))) 

CL-USER> (gen-seq:seq->list (gen-seq:seq-map #'extract-entry entries)) 
(((("message" ("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
    ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
    ("sender" ("id" . "1695095647186162"))))) 

和它的工作,但是當我串連的功能我得到這個問題:

CL-USER> (trace extract-entry extract-messaging) 
(EXTRACT-ENTRY EXTRACT-MESSAGING) 


CL-USER> (gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) 
    0: (EXTRACT-ENTRY 
     (("messaging" 
     (("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
     ("time" . 1496071518212) ("id" . "474086316315717"))) 
    0: EXTRACT-ENTRY returned 
     ((("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
    0: (EXTRACT-MESSAGING 
     ((("message" ("text" . "hola") ("seq" . 3227) 
     ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162"))))) 
; Evaluation aborted on #<TYPE-ERROR expected-type: 
      "(OR (VECTOR CHARACTER) (VECTOR NIL) BASE-STRING SYMBOL CHARACTER)" 
      datum: ("message" ("text" . "hola") ("seq" . 3227) ..)>. 

這個輸出調試器:

The value 
    ("message" ("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 

is not of type 
    (OR (VECTOR CHARACTER) (VECTOR NIL) BASE-STRING SYMBOL 
     CHARACTER) 

when binding SB-IMPL::STRING2 
    [Condition of type TYPE-ERROR] 

Restarts: 
0: [*ABORT] Return to SLIME's top level. 
1: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1003180003}>) 

Backtrace: 
    0: (STRING= "message" ("message" ("text" . "hola") ("seq" . 3227) ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u"))) [more] 
    1: (SB-KERNEL:%ASSOC-TEST "message" #<unavailable argument> #<FUNCTION STRING=>) 
    2: (EXTRACT-MESSAGING ((("message" # # #) ("timestamp" . 1496071517968) ("recipient" #) ("sender" #)))) 
    3: (SB-DEBUG::TRACE-CALL #<SB-DEBUG::TRACE-INFO EXTRACT-MESSAGING> #<FUNCTION EXTRACT-MESSAGING> ((("message" # # #) ("timestamp" . 1496071517968) ("recipient" #) ("sender" #)))) 
    4: ((LABELS GENERIC-SEQ::TRAVERSE :IN GENERIC-SEQ::SEQ-MAP-1) (((# # # #)) . #<CLOSURE (LAMBDA NIL :IN GENERIC-SEQ::SEQ-MAP-1) {1004CF1F5B}>)) 
    5: (GENERIC-SEQ:SEQ->LIST #S(GENERIC-SEQ::BASIC-SEQ :DELAYED-ENUM #<CLOSURE (LAMBDA NIL :IN GENERIC-SEQ::SEQ-MAP-1) {1004C9A46B}>)) 
    6: (SB-INT:SIMPLE-EVAL-IN-LEXENV (GENERIC-SEQ:SEQ->LIST (GENERIC-SEQ:SEQ-MAP (FUNCTION EXTRACT-MESSAGING) (GENERIC-SEQ:SEQ-MAP # ENTRIES))) #<NULL-LEXENV>) 
    7: (EVAL (GENERIC-SEQ:SEQ->LIST (GENERIC-SEQ:SEQ-MAP (FUNCTION EXTRACT-MESSAGING) (GENERIC-SEQ:SEQ-MAP # ENTRIES)))) 
    8: (SWANK::%EVAL-REGION "(gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) ..) 
    9: ((LAMBDA NIL :IN SWANK::%LISTENER-EVAL)) 
10: (SWANK-REPL::TRACK-PACKAGE #<CLOSURE (LAMBDA NIL :IN SWANK::%LISTENER-EVAL) {1004C9A1CB}>) 
11: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CLOSURE (LAMBDA NIL :IN SWANK::%LISTENER-EVAL) {1004C9A1AB}>) 
12: (SWANK::%LISTENER-EVAL "(gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) ..) 
13: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK-REPL:LISTENER-EVAL "(gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) ..) 
14: (EVAL (SWANK-REPL:LISTENER-EVAL "(gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) ..) 
15: (SWANK:EVAL-FOR-EMACS (SWANK-REPL:LISTENER-EVAL "(gen-seq:seq->list (gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries))) ..) 
16: (SWANK::PROCESS-REQUESTS NIL) 
17: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS)) 
18: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS)) 
19: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {100317FFEB}>) 
20: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/Users/toni/.roswell/lisp/slime/2017.02.27/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {.. 
21: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #1=#<SWANK/GRAY::SLIME-INPUT-STREAM {100309EAE3}>) (*STANDARD-OUTPUT* . #2=#<SWANK/GRAY::SLIME-OUTPUT-STREAM {1003167973}>) (*TRACE-OUTPUT* . #2#) (*ERR.. 
22: (SWANK::HANDLE-REQUESTS #<SWANK::MULTITHREADED-CONNECTION {10030004A3}> NIL) 
23: ((FLET #:WITHOUT-INTERRUPTS-BODY-1159 :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE)) 
24: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE)) 
25: ((FLET #:WITHOUT-INTERRUPTS-BODY-358 :IN SB-THREAD::CALL-WITH-MUTEX)) 
26: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {8A4DCFB}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD ".. 
27: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "repl-thread" RUNNING {1003180003}> NIL #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::SPAWN-REPL-THREAD) {100317FF6B}> (#<SB-THREAD:THREAD "re.. 
28: ("foreign function: call_into_lisp") 
29: ("foreign function: new_thread_trampoline") 
30: ("foreign function: _pthread_body") 
31: ("foreign function: _pthread_body") 
32: ("foreign function: thread_start") 

在這一點上問題是extract-entry返回一個列表,所以我應該像這樣工作:

CL-USER> (apply #'mapcar #'extract-messaging (mapcar #'extract-entry entries)) 
    0: (EXTRACT-ENTRY 
     (("messaging" 
     (("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
     ("time" . 1496071518212) ("id" . "474086316315717"))) 
    0: EXTRACT-ENTRY returned 
     ((("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
    0: (EXTRACT-MESSAGING 
     (("message" ("text" . "hola") ("seq" . 3227) 
     ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
    0: EXTRACT-MESSAGING returned 
     (("text" . "hola") ("seq" . 3227) 
     ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
((("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u"))) 

但隨後失敗,圖書館工作:

CL-USER> (apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) 

attempt to use VALUES-LIST on a dotted list: 
    #S(GENERIC-SEQ::BASIC-SEQ 
    :DELAYED-ENUM #<CLOSURE (LAMBDA() 
           :IN 
           GENERIC-SEQ::SEQ-MAP-1) {100499978B}>) 
    [Condition of type SIMPLE-TYPE-ERROR] 

Restarts: 
0: [*ABORT] Return to SLIME's top level. 
1: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1003160003}>) 

Backtrace: 
    0: (APPLY #<FUNCTION GENERIC-SEQ:SEQ-MAP> #<CLOSURE SB-IMPL::ENCAPSULATION {1002E5970B}> #S(GENERIC-SEQ::BASIC-SEQ :DELAYED-ENUM #<CLOSURE (LAMBDA NIL :IN GENERIC-SEQ::SEQ-MAP-1) {100499978B}>)) 
    1: (SB-INT:SIMPLE-EVAL-IN-LEXENV (APPLY (FUNCTION GENERIC-SEQ:SEQ-MAP) (FUNCTION EXTRACT-MESSAGING) (GENERIC-SEQ:SEQ-MAP (FUNCTION EXTRACT-ENTRY) ENTRIES)) #<NULL-LEXENV>) 
    2: (EVAL (APPLY (FUNCTION GENERIC-SEQ:SEQ-MAP) (FUNCTION EXTRACT-MESSAGING) (GENERIC-SEQ:SEQ-MAP (FUNCTION EXTRACT-ENTRY) ENTRIES))) 
    3: (SWANK::%EVAL-REGION "(apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) ..) 
    4: ((LAMBDA NIL :IN SWANK::%LISTENER-EVAL)) 
    5: (SWANK-REPL::TRACK-PACKAGE #<CLOSURE (LAMBDA NIL :IN SWANK::%LISTENER-EVAL) {100499951B}>) 
    6: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CLOSURE (LAMBDA NIL :IN SWANK::%LISTENER-EVAL) {10049994FB}>) 
    7: (SWANK::%LISTENER-EVAL "(apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) ..) 
    8: (SB-INT:SIMPLE-EVAL-IN-LEXENV (SWANK-REPL:LISTENER-EVAL "(apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) ..) 
    9: (EVAL (SWANK-REPL:LISTENER-EVAL "(apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) ..) 
10: (SWANK:EVAL-FOR-EMACS (SWANK-REPL:LISTENER-EVAL "(apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq-map #'extract-entry entries)) ..) 
11: (SWANK::PROCESS-REQUESTS NIL) 
12: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS)) 
13: ((LAMBDA NIL :IN SWANK::HANDLE-REQUESTS)) 
14: (SWANK/SBCL::CALL-WITH-BREAK-HOOK #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {100315FFEB}>) 
15: ((FLET SWANK/BACKEND:CALL-WITH-DEBUGGER-HOOK :IN "/Users/toni/.roswell/lisp/slime/2017.02.27/swank/sbcl.lisp") #<FUNCTION SWANK:SWANK-DEBUGGER-HOOK> #<CLOSURE (LAMBDA NIL :IN SWANK::HANDLE-REQUESTS) {.. 
16: (SWANK::CALL-WITH-BINDINGS ((*STANDARD-INPUT* . #1=#<SWANK/GRAY::SLIME-INPUT-STREAM {100307F5A3}>) (*STANDARD-OUTPUT* . #2=#<SWANK/GRAY::SLIME-OUTPUT-STREAM {1003147DD3}>) (*TRACE-OUTPUT* . #2#) (*ERR.. 
17: (SWANK::HANDLE-REQUESTS #<SWANK::MULTITHREADED-CONNECTION {10030004A3}> NIL) 
18: ((FLET #:WITHOUT-INTERRUPTS-BODY-1159 :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE)) 
19: ((FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE)) 
20: ((FLET #:WITHOUT-INTERRUPTS-BODY-358 :IN SB-THREAD::CALL-WITH-MUTEX)) 
21: (SB-THREAD::CALL-WITH-MUTEX #<CLOSURE (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE) {8A57CFB}> #<SB-THREAD:MUTEX "thread result lock" owner: #<SB-THREAD:THREAD ".. 
22: (SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE #<SB-THREAD:THREAD "repl-thread" RUNNING {1003160003}> NIL #<CLOSURE (LAMBDA NIL :IN SWANK-REPL::SPAWN-REPL-THREAD) {100315FF6B}> (#<SB-THREAD:THREAD "re.. 
23: ("foreign function: call_into_lisp") 
24: ("foreign function: new_thread_trampoline") 
25: ("foreign function: _pthread_body") 
26: ("foreign function: _pthread_body") 
27: ("foreign function: thread_start") 

的問題是相同的,但後來我可以解決這個問題:

CL-USER> (gen-seq:seq->list (apply #'gen-seq:seq-map #'extract-messaging (gen-seq:seq->list (gen-seq:seq-map #'extract-entry entries)))) 
    0: (EXTRACT-ENTRY 
     (("messaging" 
     (("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
     ("time" . 1496071518212) ("id" . "474086316315717"))) 
    0: EXTRACT-ENTRY returned 
     ((("message" ("text" . "hola") ("seq" . 3227) 
      ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
    0: (EXTRACT-MESSAGING 
     (("message" ("text" . "hola") ("seq" . 3227) 
     ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
     ("timestamp" . 1496071517968) ("recipient" ("id" . "474086316315717")) 
     ("sender" ("id" . "1695095647186162")))) 
    0: EXTRACT-MESSAGING returned 
     (("text" . "hola") ("seq" . 3227) 
     ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u")) 
((("text" . "hola") ("seq" . 3227) 
    ("mid" . "mid.$cAAGvLYgmIaVihhT_EFcVM-1tP17u"))) 

但是,當我這樣做,我失去了懶評估術語如此,我怎樣才能在不失去通用序列中的懶惰評估的情況下實現它。

+0

看起來有太多的列表級別。 ASSOC沒有得到關聯列表。它得到一個關聯列表的列表。 EXTRACT -MESSAGING相同... –

+0

如果一個函數需要一個關聯列表作爲參數,我會向該函數的主體添加一個ASSERT語句,該語句檢查它實際上是否是一個正確的關聯列表。 –

回答

4

如果與assoc命令列表你的函數交易,你可能會檢查他們實際上得到有效的assoc命令列表與這樣的功能:

(defun assert-valid-alist (alist) 
    (assert (and (not (null alist))  ; not the empty list 
       (listp alist)   ; it is a list 
       (every #'consp alist) ; every item is a cons 
       (every (lambda (item)  
         (symbolp (car item))) ; every key should be a symbol 
         alist)) 
     (alist) 
    "Not a valid assoc list: ~a" alist)) 

(defun get-age (person) 
    (assert-valid-alist person) 
    (cdr (assoc 'age person))) 

例子:

CL-USER 106 > (get-age '((name . ute) (age . 34))) 
34 

CL-USER 107 > (get-age '(((name . ute) (age . 34)))) 

Error: Not a valid assoc list: (((NAME . UTE) (AGE . 34))) 
    1 (continue) Retry assertion with new value for ALIST. 
    2 (abort) Return to level 0. 
    3 Return to top loop level 0. 

這可能性價比和可能一旦代碼正常工作,您可以將其刪除。

+0

你是對的,但這裏的問題是我有像這樣的嵌套結構CL-USER>(get-age'((name。ute)(age。34)(adresses。(((street。patata)(city。 bigcity))((street。tomate)(city。funcity)))))) 34,現在條目和消息只有一個元素。並且我將seq-map應用於這些元素,它可以工作,但是當我嵌套它時,它不起作用 – anquegi

+0

我編輯了一個重要的嵌套列表工作的答案 – anquegi

+0

感謝您的回答,這是要初始化解決真正的問題。總是你必須知道你在做什麼 – anquegi