1
\$\begingroup\$

I ran across this challenge. Which has this answer.

(loop)

which is cited as having 6 characters. My problem is that when using SBCL and emacs-slime. Doing a macro expansion C-x C-m leads to

(BLOCK NIL (TAGBODY #:G890 (PROGN) (GO #:G890)))

Which is significantly more than 6 characters. Now the question arises how to count characters in this case. If one allows macros as a valid tool (as loop in SBCL seems to be implemented as a macro) anyone could come up with another macro shortening the loop to 3 characters (or maybe even less).

One might argue that loop is part of SBCL implementation thus no extra macro is required. But it still feels like cheating using a macro based solution as the 'really' used amount of characters is different.

| |
\$\endgroup\$
  • \$\begingroup\$ Not only is this part of SBCL implementation, it is defined by the language standard. \$\endgroup\$ – coredump Oct 6 '15 at 13:16
  • \$\begingroup\$ @coredump I was referring to the implementation as a macro as SBCL specific. One could skip that step and directly translate the loop command into the machine code. Thus the implementation of loop is implementation (of lisp) depending. \$\endgroup\$ – Sim Oct 6 '15 at 17:45
  • \$\begingroup\$ But loop is guaranteed by specification to behave as a macro: there is a macro function that perform macro expansion and result into another form. A compiler could bypass the macro and do its tricks, but how is this different than a compiler for C? We don't compare machine codes. Of course the implementation of the macro is left to the implementation (e.g. ABCL macroexpands (loop) as (BLOCK NIL (TAGBODY #:G44 (GO #:G44))), which is different from above). I don't understand your concern, sorry. \$\endgroup\$ – coredump Oct 6 '15 at 19:29
  • \$\begingroup\$ @coredump I was unaware that the specs also specified that loop has to behave as a macro. Thus, my point was void. \$\endgroup\$ – Sim Oct 6 '15 at 19:38
  • \$\begingroup\$ Well, that how I understand it. It is noted "macro" and thus "macro-function" should return a function that performs macroexpansion, so I don't think an implementation is allowed to not provide macroexpansion for it, even though it might be possible to compile a specific macro in a different, yet compatible way. Cheers. \$\endgroup\$ – coredump Oct 6 '15 at 19:43
6
\$\begingroup\$

Macros act on the parsed data-structure, not text. The source code is the string "(loop)", which is used to determine the score. Once this string has been read, it is no longer valid to talk about the "real" amount of characters: the AST is made of lists, vectors, symbols and other literal values which are being transformed to produce the code that is going to be evaluated.

The code printed by macroexpansion is not readable anymore as an equivalent of the original one: there are uninterned symbols like #:G890, which refer to fresh symbols each time they are read (interned symbols map to the same symbol object in memory). It would not be fair to submit the expanded code because nobody could execute it (even if it can be evaluated, the result would be different than the original code). To be fair, if you bind *print-circle* to T, the macroexpanded code is printed readably, but the point is that macros are not just a string preprocessor on top of the language. They are part of Common Lisp and as such they belong to the set of features we have the right to use and count as source code.

That being said, it generally does not pay off to define custom macros in code-golf anyway.

Nothing said here is specific to SBCL.

| |
\$\endgroup\$
10
\$\begingroup\$

I'm not familiar with SBCL, but here's my take on the situation.

If the macro is part of the implementation and nothing needs to be done to include it, then it should be fine. If something does need to be done to include it however, e.g. by some sort of import statement or compiler flag, then that should be included in the byte count. This is to stop non-standard loopholes like the -D flag in C, which allows one to define an expansion such that all "programs" are 1 byte in size.

In this situation, if (loop) is valid as is with the implementation, then these 6 bytes should be counted. However, if someone wanted to define their own macro, say l, then the macro definition needs to be in the byte count as well (I'm guessing that wouldn't be worth it here).

I can't think of a good reason why the expansion should be counted instead, since to me this feels like a form of syntactic sugar.

| |
\$\endgroup\$
1
\$\begingroup\$

Extending slightly, the same problem can arise in C. Technically #include <stdio.h> is a file of 12539 characters!

I think it's reasonable to say that the text you feed into your compiler / interpreter is the "size of program", regardless how the compiler / interpreter then executes (by macro expansion / text replacement / tokenising / whatever).

| |
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .