Lo que usted solicita es engañoso. Este es un trabajo para macros, como ya han expuesto los demás. Exploraré una posibilidad diferente: usar los mismos símbolos pero poner algunos envoltorios alrededor del código que desea escribir. La ventaja de esta técnica es que el código se transforma "léxicamente" y en "tiempo de compilación", en lugar de en tiempo de ejecución (como en las otras respuestas). En general, esto es más rápido y más fácil de depurar.
lo tanto, aquí es una función que transformaría el With
con su sintaxis propuesta:
Clear[expandWith];
expandWith[heldCode_Hold] :=
Module[{with},
heldCode /. With -> with //. {
HoldPattern[with[{{} = {}, rest___}, body_]] :>
with[{rest}, body],
HoldPattern[
with[{
Set[{var_Symbol, otherVars___Symbol}, {val_, otherVals___}], rest___},
body_]] :>
with[{{otherVars} = {otherVals}, var = val, rest}, body]
} /. with -> With]
Tenga en cuenta que este opera en código retenida. Esto tiene la ventaja de que no tenemos que preocuparnos por la posible evaluación del código ni al principio ni cuando finaliza expandWith
. Aquí está cómo funciona:
In[46]:= [email protected][With[{{x1,x2,x3}={a,b,c}},x+x1+x2+x3]]
Out[46]= Hold[With[{x3=c,x2=b,x1=a},x+x1+x2+x3]]
Esto, sin embargo, no es muy cómodo de usar.Aquí es una función de la conveniencia de simplificar esto:
ew = Function[code, [email protected]@[email protected], HoldAll]
podemos utilizar ahora como:
In[47]:= [email protected][{{x1,x2}={a,b}},x+x1+x2]
Out[47]= a+b+x
Por lo tanto, para que la expansión ocurra en el código, simplemente envuelva ew
alrededor de ella. Aquí está su caso, para la definición de la función:
Remove[f];
ew[f[x_] := With[{{x1, x2} = {a, b}}, x + x1 + x2]]
Ahora comprobar y ver que lo que tenemos es una definición más amplia:
?f
Global`f
f[x_]:=With[{x2=b,x1=a},x+x1+x2]
La ventaja de este enfoque es que se puede envolver ew
en torno a una arbitrariamente gran parte de tu código. Lo que sucede es que primero se genera código expandido a partir de él, como si lo escribiera usted mismo, y luego ese código se ejecuta. Para el caso de las definiciones de función, como f
anterior, podemos decir que la generación de código ocurre en "tiempo de compilación", por lo que evita cualquier sobrecarga en tiempo de ejecución cuando use la función más tarde, lo que puede ser sustancial si la función se llama con frecuencia.
Otra ventaja de este enfoque es su capacidad de compilación: puede obtener muchas extensiones de sintaxis, y para cada una de ellas escribir una función similar a ew
. Luego, siempre que estas funciones personalizadas de transformación de códigos no se concuerden entre sí, simplemente puede componerlas (anidar) para obtener un efecto acumulativo. En cierto sentido, de esta manera usted crea un generador de código personalizado que genera código válido de Mathematica a partir de algunas expresiones de Mathematica que representan programas en su lenguaje personalizado, que puede crear dentro de Mathematica usando estos medios.
EDITAR
Al escribir expandWith
, que utiliza la aplicación de reglas iterativo para evitar el trato con el control de la evaluación, que puede ser un desastre. Sin embargo, para los interesados, aquí hay una versión que hace un trabajo explícito con fragmentos de código no evaluados.
Clear[expandWithAlt];
expandWithAlt[heldCode_Hold] :=
Module[{myHold},
SetAttributes[myHold, HoldAll];
heldCode //. HoldPattern[With[{Set[{vars__}, {vals__}]}, body_]] :>
With[{eval =
(Thread[Unevaluated[Hold[vars] = Hold[vals]], Hold] /.
Hold[decl___] :> myHold[With[{decl}, body]])},
eval /; True] //. myHold[x_] :> x]
Aunque me parece mucho más complicado que el primero.
A menudo reflexiono sobre tales elecciones de diseño, y a veces publico tales preguntas aquí. Lamentablemente, es raro que tales cosas se expliquen. Me he contentado con el hecho de que With/Block/Module solo funciona de manera diferente, y que 'Set' en el primer argumento de estos no está realmente realizando la operación' Set', sino que es sintaxis. –
De mi lectura de la documentación del mensaje de error (parte citada al final de mi Q), me parece que hay una coincidencia de patrón simple que impulsa el comportamiento actual, es decir, que acepta patrones que tienen la Lista principal, que contiene solo elementos que evalúan a True para algo como MatchQ [Hold [Set [x, 1]], Hold [Set [Symbol_, _]]]. Si este es el caso, sería posible, al menos en mi pequeño mundo miope, modificar la coincidencia/prueba de patrones para permitir el comportamiento que busco, y que la documentación sobre Set parece implicar que debería funcionar (como una forma válida) de asignación). – telefunkenvf14
No estoy en desacuerdo, pero no conozco ninguna forma de efectuar ese cambio. –