首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ES6风格的Parenscript类

ES6风格的Parenscript类
EN

Stack Overflow用户
提问于 2018-02-05 18:39:32
回答 2查看 342关注 0票数 2

是否有合适的方法来编写输出ES6类定义的Parenscript类宏?

如果类定义如下所示:

代码语言:javascript
复制
class Person {
    sayHello() {
        alert('hello');
    }

    walk() {
        alert('I am walking!');
    }
}

class Student extends Person {
    sayGoodBye() {
        alert('goodBye');
    }

    sayHello() {
        alert('hi, I am a student');
    }
}

我想在Parenscript中这样写:

代码语言:javascript
复制
(def-class -person ()
  (say-hello () (alert "hello"))
  (walk () (alert "I am walking!")))

(def-class -student (-person)
  (say-good-bye () (alert "goodBye"))
  (say-hello () (alert "hi, I am a student")))

我尝试了两种方法--附在下面的答案--但这两种方法都不完全令人满意。有没有更好的解决方案,不涉及再工程的部分记录?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-02-05 18:39:32

解决方案1:

代码语言:javascript
复制
(defpsmacro def-class (name (&optional extends) &body body)
  (multiple-value-bind (constructor others)
      (gadgets:splitfilter (lambda (x) (string-equal (car x) 'constructor)) body)
    (let ((constructor (case (length constructor)
                         (0 nil)
                         (1 (car constructor))
                         (otherwise
                          (error "Class can't have more than one constructor"))))
          (const-lambda-list nil)
          (const-body nil))
      (when constructor
        (setf const-lambda-list (second constructor))
        (set const-body (cddr constructor)))
      `(progn
         (defun ,name ,const-lambda-list
           ,@const-body)
         ,@(mapcar
            (lambda (item)
              `(setf (@ ,name prototype ,(car item))
                     (lambda ,(second item) ,@(cddr item))))
            others)
         ,@(when extends
                 `((setf (@ ,name prototype) (chain -object (create (@ ,name prototype))))
                   (setf (@ ,name prototype constructor) ,name)))))))

问题:

  • 输出ES5 javascript。
  • 不支持静态方法。
票数 4
EN

Stack Overflow用户

发布于 2018-02-05 18:49:24

解决方案2:

代码语言:javascript
复制
(defpsmacro def-class-es6 (name (&optional extends) &body body)
  (let ((output nil))
    (push (format nil "class ~a~a {~&"
                  (symbol-to-js-string name)
                  (if extends
                      (format nil " extends ~a" (symbol-to-js-string extends))
                      ""))
          output)
    (dolist (itm body)
      (when (atom itm)
        (error "Non-list item found in class body."))
      (let ((staticp nil))
        (when (eq (car itm) :static)
          (setf itm (if (listp (cadr itm)) (cadr itm) (cdr itm)))
          (setf staticp t))
        (destructuring-bind (mname lambda-list . statements) itm
          (push
           (format
            nil "~a~a (~{~a~^ ~}) {~a}~&"
            (if staticp "static " "")
            (symbol-to-js-string mname)
            (mapcar #'symbol-to-js-string lambda-list)
            ;; Use parenscript to express a method body, then peel the
            ;; block contents out and put them in our own block.
            (let ((fbody (eval `(ps (lambda ,lambda-list ,@statements)))))
              (subseq fbody
                      (1+ (position #\{ fbody))
                      (position #\} fbody :from-end t))))
           output))))
    (push "}" output)
    `(lisp-raw ,(apply #'concatenate 'string (nreverse output)))))

这个宏输出ES6代码,但是:

  • 依赖于我的父母记录扩展,这不是在官方的分发。
  • 是很讨厌的,而且不会很好的缩进。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48629336

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档