Elsa icon indicating copy to clipboard operation
Elsa copied to clipboard

Write some crazy destructuring macro that can take forms and pluck out data

Open Fuco1 opened this issue 7 years ago • 1 comments

See for example

(cl-defmethod elsa-check-check ((_ elsa-check-lambda-eta-conversion) form scope state)
  (let* ((seq (oref form sequence))
         (arg-list (elsa-form-sequence (nth 1 seq)))
         (body (nthcdr 2 seq)))
    (when (= 1 (length body))
      (let ((fn-form (car body)))
        (when (elsa-form-list-p fn-form)
          (let ((fn-args (cdr (elsa-form-sequence fn-form))))
            (when (and (= (length arg-list) (length fn-args))
                       (-all-p
                        (-lambda ((lambda-arg . fn-arg))
                          (and (elsa-form-symbol-p fn-arg)
                               (eq (elsa-form-name lambda-arg)
                                   (elsa-form-name fn-arg))))
                        (-zip arg-list fn-args)))
              (elsa-state-add-error state
                (elsa-make-notice (format "You can eta convert the lambda form and use the function `%s' directly"
                                          (symbol-name (elsa-form-name fn-form)))
                                  (elsa-form-car form))))))))))

This is quite complicated function which does essentially nothing except check if the body is of length 1 and then compare two lists.

I can imagine something like

(defmacro elsa-match-form (&rest)
  (declare (indent 2))
  )

(elsa-match-form form
    (:symbol (:list args) (&rest body))
  (elsa-match-form body
      ((:list first)) ;; list of one thing which is a list form
    (elsa-match-form first
        (:symbol name)) ;; gives me the symbol form... but all I really care is the name?, maybe I could use (:symbol-name name)
    ...
    ))

Obviously this should be nestable recursively... and maybe with multiple options like pcase. The syntax needs to be very light and only work with the syntax.

Fuco1 avatar Aug 16 '18 17:08 Fuco1

Something not that bad can be achieved with pcase already out of the box, but it is still not very clear, especially with the "useless" eieio markers

;; pcase matcher
(pcase my-lambda-form
  ((and (pred elsa-form-list-p)
        (eieio (sequence `(,(eieio name) ,lb-args ,(eieio (sequence `(,(eieio (name fn-name)) . ,fn-args)))))))
   (list :name name
         :args lb-args
         :fn-name fn-name
         :fn-args fn-args)))

;; form
(lambda (x) (+ x))

;; reader form
(setq my-lambda-form [eieio-class-tag--elsa-form-list 102 120 nil 6 0
                                 [eieio-class-tag--elsa-type-mixed]
                                 nil unbound
                                 ([eieio-class-tag--elsa-form-symbol 103 109 nil 6 1
                                                                     [eieio-class-tag--elsa-type-mixed]
                                                                     nil unbound lambda]
                                  [eieio-class-tag--elsa-form-list 110 113 nil 6 8
                                                                   [eieio-class-tag--elsa-type-mixed]
                                                                   nil unbound
                                                                   ([eieio-class-tag--elsa-form-symbol 111 112 nil 6 9
                                                                                                       [eieio-class-tag--elsa-type-mixed]
                                                                                                       nil unbound x])]
                                  [eieio-class-tag--elsa-form-list 114 119 nil 6 12
                                                                   [eieio-class-tag--elsa-type-mixed]
                                                                   nil unbound
                                                                   ([eieio-class-tag--elsa-form-symbol 115 116 nil 6 13
                                                                                                       [eieio-class-tag--elsa-type-mixed]
                                                                                                       nil unbound +]
                                                                    [eieio-class-tag--elsa-form-symbol 117 118 nil 6 15
                                                                                                       [eieio-class-tag--elsa-type-mixed]
                                                                                                       nil unbound x])])])

Fuco1 avatar Aug 17 '18 11:08 Fuco1