Inverted syntax: Difference between revisions

Content added Content deleted
Line 49: Line 49:
<lang go>m[k] = v, ok</lang>
<lang go>m[k] = v, ok</lang>
Here, <tt>ok</tt> can be any expression that evaluates to a bool. The value will be set in the map if <tt>ok</tt> is true. If <tt>ok</tt> is false, any value stored in the map under that key will be ''deleted'' from the map.
Here, <tt>ok</tt> can be any expression that evaluates to a bool. The value will be set in the map if <tt>ok</tt> is true. If <tt>ok</tt> is false, any value stored in the map under that key will be ''deleted'' from the map.

=={{header|Common Lisp}}==

Lisp has a PROGN macro for evaluating a bunch of forms, such that the value(s) of the last one is yielded as the result of the PROGN. We can create a reversed analog of PROGN, inside which, we must write the syntax backwards: arguments first, then the operator. Furthermore, this rule is recursively applied to expressions.

''Note: unfortunately this is completely naive. To do this 100% right, we need a code walker, which is more complicated. However, code walkers are used in practice for hairy language transformation jobs, just not commonly so in daily Lisp programming. A code walker would let us imlement a more smarter version which would apply the transformation to forms which are evaluated, and not things like literal data. As it is, our macro also transforms literal data, making it impossible, for instance, to use the quote shorthand 'FORM. This stands for (QUOTE FORM) and of course, the macro will treat it as reversed syntax, transforming it to (FORM QUOTE). We could hack in a special case which recognized QUOTE, but then we do not know whether or not (QUOTE FORM) is in a context where it is being evaluated. That is why we need the code walker. It's best to use someone's well-tested, portable code-walker, since they are not trivial to write, and they have some implementation-specific parts (such as recognition of compiler-specific forms that come out of system macros or perhaps out of user-written nonportable code).''


<lang lisp>(eval-when (:compile-toplevel :load-toplevel :execute)
(defun unrev-syntax (form)
(cond
((atom form) form)
((null (cddr form)) form)
(t (destructuring-bind (oper &rest args) (reverse form)
`(,oper ,@(mapcar #'unrev-syntax args)))))))

(defmacro rprogn (&body forms)
`(progn ,@(mapcar #'unrev-syntax forms)))</lang>

Test run:

<pre>$ clisp -q -i reverse.lisp
;; Loading file reverse.lisp ...
;; Loaded file reverse.lisp
[1]> (rprogn ((1 2 +) (3 4 +) *))
21
[2]> (rprogn (("not greater" print) ("greater" print) (1 2 >) if))

"greater"
"greater"
[3]> (macroexpand '(rprogn (("not greater" print) ("greater" print) (1 2 >) if)))
(PROGN (IF (> 2 1) (PRINT "greater") (PRINT "not greater"))) ;
T
</pre>


=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==