macro-exercises.scm 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. ;;Here are two macro ideas (the derivative idea is going to be too much work at the moment):
  2. ;; write a if-not macro that swaps the order of the then and else branches:
  3. (defmacro (if-not fool yes no)
  4. `(if ,fool
  5. ,no
  6. ,yes))
  7. (TEST
  8. > (if-not (< 10 11) "no" "yes")
  9. "yes")
  10. ;write a nif macro that takes any number of branches, similar to cond, but without parens around the test and subsequent then branch; the last branch should be the else branch:
  11. (def (nif-expand args) (if-let-list ))
  12. (TEST
  13. > (def (t a b c)
  14. (nif a "a" b "b" c "c" "none"))
  15. > (t #f #f #f)
  16. "none"
  17. > (t #f #f #t)
  18. "c"
  19. > (t #t #f #t)
  20. "a"
  21. > (t #t #t #t)
  22. "a"
  23. > (t #f #t #t)
  24. "b")
  25. (defmacro (nif . args)
  26. `(if-let-list ((,args) (args)))
  27. "none")
  28. ;;- write a var macro that takes a string as its argument, which is the name of the variable it should reference.
  29. (TEST
  30. > (let ((a 10) (b 20))
  31. (+ (var "a") (var "b")))
  32. 30)
  33. ;; You'll need to use assert* again, as well as string->symbol.
  34. ;; write a for macro that works similar to Python:
  35. (TEST
  36. > (def vals '())
  37. > (for x '(1 4 5 6) (push! vals (* 3 x)))
  38. > vals
  39. (18 15 12 3))
  40. ;;Note: use the .for-each method, which takes a list or vector as its first argument and a procedure of one argument as its second argument.