syntax-objects / Summer2021

Syntax Parse Bee 2021
11 stars 3 forks source link

`displayln*` - a macro with similar use to python's `print` #2

Open Lazerbeak12345 opened 3 years ago

Lazerbeak12345 commented 3 years ago

Please enter the bee by submitting code (or links to code) for:

  1. your macro
  2. an example use of your macro
  3. (optional) "before" code that your macro helps to improve

Thank you for your submission!

If your entry is a PR to the syntax parse examples repository, please include a link to the PR.

Macro

Paste the code for your macro here. Please explain the purpose of the macro.

#lang racket
(require syntax/parse/define)
#|This macro is intended to make debugging easier by allowing a programmer to
print a batch of values all in one go much like python's `print`

To change the output port use `parameterize`.|#
(define-syntax-parse-rule (displayln* items:expr ...)
  (println (string-join (map ~a (list items ...)) " ")))

I can easily rewrite this without using the define-syntax-parse-rule macro (which expands down to a call to syntax-parse and a bit of boilerplate), but I chose this approach because of how readable (and thus maintainable) the result is if this were used in real code.

Example

Illustrate one or more ways of using your macro. Please show code and briefly describe what it does.

(displayln* 1 2 3 4 5 '(this is a list of datums 1 2 3 "hi"))
; should print "1 2 3 4 5 '(this is a list of datums 1 2 3 \"hi\")\n" exactly

Before and After

If you designed your macro to improve some existing code, please explain the improvements.

Use the following categories if applicable:

  • Code Cleaning : Please share the code that you used to write before creating your macro. Briefly explain how the code works.
  • Macro Engineering : Please share the old macro that you revised. Briefly explain the changes.

Before I would have used formats like this:

(println (format "~a ~a ~a" 1 2 '(a b)))

Now the same code can be written like this:

(displayln* 1 2 '(a b))

One downside is that specifying the port can't be done with the last argument anymore, but the simple workaround for that case is simply using parameterize on (current-output-port):

before

(println (format "~a ~a ~a" 1 2 '(a b)) the-port)

after:

(parameterize ([current-output-port the-port])
   (displayln* 1 2 '(a b)))

Licence

Please confirm that you are submitting this code under the same MIT License that the Racket language uses. https://github.com/racket/racket/blob/master/racket/src/LICENSE-MIT.txt Please confirm that the associated text is licensed under the Creative Commons Attribution 4.0 International License http://creativecommons.org/licenses/by/4.0/

I confirm that the code is under the same license as the Racket language, and associated text is under Creative Commons Attribution 4.0 International License

Contact

To receive prizes and/or provide feedback please complete the form at https://forms.gle/Z5CN2xzK13dfkBnF7 (google account not required / email optional).

The google form didn't work...

bennn commented 3 years ago

Thank you for entering!!

Please try the form again. I clicked a button to have it start collecting entries. https://forms.gle/Z5CN2xzK13dfkBnF7 (No idea why it stopped in the first place)

Lazerbeak12345 commented 2 years ago

Reading over this again, this looks doable with just a define form - no macros. I'm... not familiar enough with define to say for sure though.

bennn commented 2 years ago

Yep that's true. Here's the define syntax:

(define (displayln* . items)
  (println (string-join (map ~a items) " ")))

But still, it's nice to have simple useful examples to see how things like ... work.