threading-chain-pipe.scm 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. (library (threading-macro)
  2. (export ->)
  3. (import
  4. (except (rnrs base))
  5. (only (guile))))
  6. ;; The following macro was suggested by Mark H. Weaver on
  7. ;; the Guile Scheme user mailing list, as a response to a
  8. ;; different formulation of Chris Vine, also on the Guile
  9. ;; Scheme user mailing list, in the context of writing a
  10. ;; threading macro.
  11. ;; Comments added by me.
  12. (define-syntax ->
  13. ;; We are not defining any literals.
  14. (syntax-rules ()
  15. ;; Base case. If there is only the initial expression,
  16. ;; it means, that no operations are applied, so the
  17. ;; expression is already the result of the pipe.
  18. [(-> exp) exp]
  19. ;; If there is an arbitrary number of expressions `exp
  20. ;; ...` followed by one final expression `(op args
  21. ;; ...)`, which consists of an operation `op` and an
  22. ;; arbitrary number of arguments `args ...` for that
  23. ;; operation, ...
  24. [(-> exp ... (op args ...))
  25. ;; ... we destrcuture the final operation into the
  26. ;; operation name `op` and its arguments `args
  27. ;; ...`. With that we are able to make it the
  28. ;; outer-most wrapping operation call in the syntax
  29. ;; produced by the macro. Furthermore we output a new
  30. ;; macro call, which is the same, except, that it is
  31. ;; wrapped inside the last operation and does not
  32. ;; contain the last operation any longer, reducing the
  33. ;; number of expressions in the macro call. When the
  34. ;; macro is called again, it will have another
  35. ;; expression as the final operation. This will
  36. ;; continue until all expressions have been wrapped as
  37. ;; procedure calls around the initial expression and
  38. ;; the macro will go into the base case.
  39. (op args ... (-> exp ...))]))
  40. ;; From this we can easily derive a version `pipe-left`,
  41. ;; which always puts the value of the previous pipe step on
  42. ;; the left, instead of the right of given arguments to the
  43. ;; operations as follows:
  44. ;; (define-syntax pipe-left
  45. ;; (syntax-rules ()
  46. ;; [(-> exp) exp]
  47. ;; [(-> exp ... (op args ...))
  48. ;; (op (-> exp ...) args ...)]))
  49. ;; (define-syntax ->
  50. ;; (syntax-rules ()
  51. ;; ((-> exp) exp)
  52. ;; ((-> exp (proc args ...) rest ...) (-> (proc exp args ...) rest ...)
  53. ;; ((-> exp proc rest ...) (-> (proc exp) rest ...))))