等于函数

等于函数将会与排序函数有所不同,因为我们想要它不仅仅适用于数字类型。除此之外,它将用于判断输入是否为空列表,或者判断两个函数是否相同。因此我们需要定义一个用来检验两个不同类型lval变量是否相等的函数。

该函数实质上检查两个构成lval类型数据的所有字段是否相等。 若所有字段都相等,则两者被认为是相等的。 否则,若存在任何差异,则两者被认为是不相等的。

  1. int lval_eq(lval* x, lval* y) {
  2. /* Different Types are always unequal */
  3. if (x->type != y->type) { return 0; }
  4. /* Compare Based upon type */
  5. switch (x->type) {
  6. /* Compare Number Value */
  7. case LVAL_NUM: return (x->num == y->num);
  8. /* Compare String Values */
  9. case LVAL_ERR: return (strcmp(x->err, y->err) == 0);
  10. case LVAL_SYM: return (strcmp(x->sym, y->sym) == 0);
  11. /* If builtin compare, otherwise compare formals and body */
  12. case LVAL_FUN:
  13. if (x->builtin || y->builtin) {
  14. return x->builtin == y->builtin;
  15. } else {
  16. return lval_eq(x->formals, y->formals)
  17. && lval_eq(x->body, y->body);
  18. }
  19. /* If list compare every individual element */
  20. case LVAL_QEXPR:
  21. case LVAL_SEXPR:
  22. if (x->count != y->count) { return 0; }
  23. for (int i = 0; i < x->count; i++) {
  24. /* If any element not equal then whole list not equal */
  25. if (!lval_eq(x->cell[i], y->cell[i])) { return 0; }
  26. }
  27. /* Otherwise lists must be equal */
  28. return 1;
  29. break;
  30. }
  31. return 0;
  32. }

使用该函数,可以非常简单地新增用于比较是否相等的内置函数。 我们仅需要保证输入为两个参数,检验它们是否相等,然后我们将比较结果存储到一个新的lval中并返回它。

  1. lval* builtin_cmp(lenv* e, lval* a, char* op) {
  2. LASSERT_NUM(op, a, 2);
  3. int r;
  4. if (strcmp(op, "==") == 0) {
  5. r = lval_eq(a->cell[0], a->cell[1]);
  6. }
  7. if (strcmp(op, "!=") == 0) {
  8. r = !lval_eq(a->cell[0], a->cell[1]);
  9. }
  10. lval_del(a);
  11. return lval_num(r);
  12. }
  13. lval* builtin_eq(lenv* e, lval* a) {
  14. return builtin_cmp(e, a, "==");
  15. }
  16. lval* builtin_ne(lenv* e, lval* a) {
  17. return builtin_cmp(e, a, "!=");
  18. }