I prefer objective golf to the more subjective "underhanded", but if that's the demand, here you go:
stLDtsTC43a&[5]
print do [2 + 2]
That outputs 5. The real payload here could be just 8 chars of poison, +: a&[5]
, substituting the arity-2 infix function that +
is bound to by default with a prefix arity-1 function that always returns 5. Looks like other people have done the same thing and been downvoted, so I've upped the ante a bit with obfuscation.
The transparent version of the poisoning line would be:
+: function [dummy-parameter] [5]
But to try and mask it so no + appears in the poisoning code, it does stLDtsTC43a&[5]
... which translates to set load to-string to-char 43
to do the assignment. So it turns 43 into a character, then into a string, and loads it into structural code (as the single symbolic word +
) to use the SET operator on.
After that line runs, basically + anything
will will return 5. And since it isn't infix, it's not looking "behind" it to find a first parameter.
If evaluating to 5 were enough, you could just say 2 + 2
. But if a print is desired, you can't merely print [2 + 2]
and get 5, though. Because PRINT runs a REDUCE step, and keeps all of the values...so the evaluation becomes [2 5]
and it prints both numbers. However, by calling the evaluator via DO (which returns the last result, discarding results of all prior evaluations) we throw away the 2...and all PRINT sees is the last value. + 2
is 5
.
(Note: For anyone worried that this malleability points to an fatal flaw in Rebol/Red, I'll point out PROTECT:
>> protect '+
>> +: function [dummy-parameter] [5]
** Script error: protected variable - cannot modify: +:
It's a lot like a game of Nomic, for those familiar...)
echo "2+2=5";
\$\endgroup\$