首次尝试

我们的内建函数应该和上章的buildin_op接口一致。也就是说所有的参数都先转换为S-表达式,同时要注意使用后释放内存。函数的返回值将是一个新的lval*

实现Q-表达式的headtail的功能并不难。我们可以使用已有的S-表达式函数,比如lval_takelval_pop。同时我们也要对错误的输入进行异常处理。

我们先从headtail入手。它们在某些条件下是不能执行的。首先要保证输入的参数只有一个,并且类型为Q-表达式。其次这个输入的Q-表达式不能为空。

head函数可以重复执行popdelete在第二个列表元素(index 1)上,直到列表为空。

tail函数更简单。只需要popdelete第一个列表元素(index 0),剩余元素组成的列表则为我们所需要的。按此思路我们可以将代码实现如下:

  1. lval* builtin_head(lval* a) {
  2. /* Check Error Conditions */
  3. if (a->count != 1) {
  4. lval_del(a);
  5. return lval_err("Function 'head' passed too many arguments!");
  6. }
  7. if (a->cell[0]->type != LVAL_QEXPR) {
  8. lval_del(a);
  9. return lval_err("Function 'head' passed incorrect types!");
  10. }
  11. if (a->cell[0]->count == 0) {
  12. lval_del(a);
  13. return lval_err("Function 'head' passed {}!");
  14. }
  15. /* Otherwise take first argument */
  16. lval* v = lval_take(a, 0);
  17. /* Delete all elements that are not head and return */
  18. while (v->count > 1) { lval_del(lval_pop(v, 1)); }
  19. return v;
  20. }
  21. lval* builtin_tail(lval* a) {
  22. /* Check Error Conditions */
  23. if (a->count != 1) {
  24. lval_del(a);
  25. return lval_err("Function 'tail' passed too many arguments!");
  26. }
  27. if (a->cell[0]->type != LVAL_QEXPR) {
  28. lval_del(a);
  29. return lval_err("Function 'tail' passed incorrect types!");
  30. }
  31. if (a->cell[0]->count == 0) {
  32. lval_del(a);
  33. return lval_err("Function 'tail' passed {}!");
  34. }
  35. /* Take first argument */
  36. lval* v = lval_take(a, 0);
  37. /* Delete first element and return */
  38. lval_del(lval_pop(v, 0));
  39. return v;
  40. }