Re: Add syntax highlighting to own command

*To*: mathgroup at smc.vnet.net*Subject*: [mg102221] Re: Add syntax highlighting to own command*From*: earthnut at web.de (Bastian Erdnuess)*Date*: Sat, 1 Aug 2009 04:03:49 -0400 (EDT)*References*: <200907090600.CAA17547@smc.vnet.net> <h3766u$f9h$1@smc.vnet.net> <h46p70$e7l$1@smc.vnet.net>

It took me some time to answer your last posting, but here it is. Leonid Shifrin <lshifr at gmail.com> wrote: > 1. About variable renaming Hm, it was a little strange what I did. I told (principally) to translate f[ x_ ] := With[ { a = x }, a ] to With[ { a = x }, f[ x_ ] := a ] what needs some goodwill to get a propper interpretation. Also what I ment to do would translate f[ x_ ] := With[ { y = aVeryLongCalculation[x] }, y * Exp[ y ] ] to f[ x_ ] := aVeryLongCalculation * Exp[ aVeryLongCalculation[ x ] ] and run the same aVeryLongCalculation unnecessarily twice. > 2. Your workaround: > is interesting and quite inventive, but still not completely satisfactory in > my view. > 3. ToString - ToExpression cycles - my personal opinion: I went through the > stage when I was using them extensively as a cheap substitute for more > complex expressions involving Evaluate, Unevaluated, Hold and the like. I > try not to do it anymore in systematic programming. I think it is not a good > style, in particular it undermines possible introspection of the code, and a > few other reasons. I see it the same. I would have prefered to play around with the actual expression, but it is not so easy. So I tried it with the StringExpression and it worked better. But that's definitely far from optimal. With the Block trick I see now how to do it better. Seems to be not possible to control Mathematicas evaluation circle without some tricks. > the following > does exactly the same and does not require ToString-ToExpression cycle: > > > Verbatim[SetDelayed][l_, LetB[v_, Verbatim[Condition][r_, c_]]] ^:= > Module[{a}, LetB[v, Unevaluated[SetDelayed[a, r /; c]] /. a :> l]]; That is much closer to what I wanted to do. Thanks. I'll save this peace of code somewhere where I can hopefully find it again when I need it. > Anyways, while this does solve one problem, it does not solve another, more > subtle one: it is difficult to implement UpValues with SetDelayed and > Condition ourselves. There are internal heads RuleCondition and > $ConditionHold, which get executed when we execute scoping constructs > with conditions attached - we don't want this to happen prematurely. > f[x_,y_]:=Let [{xl=x,yl=y+xl+1},Print["*"];(xl^2+yl^2/;(xl+yl<15))]; > f[x_,y_]:=x+y; > > In[9] = ?f > Out[9] = > Global`f > f[x_,y_]:=x+y > > Not good, in my view. My version does this IMO more consistently: > In[12] = ?f > Out[12] = > Global`f > f[x_,y_]:=With[{xl=x},With[{yl=y+xl+1},Print[*];xl^2+yl^2/;xl+yl<15]] > f[x_,y_]:=x+y So, it seems to be necessary to unroll the whole With expression to make this things working. > 4. Block trick > > This is a very powerful but also potentially dangerous [...] > since it will block your symbol for an entire > execution stack enclosed in Block, that is, in all functions that may > be called during this execution. This is really useful. You can try Block[ { with }, foo[ with ] /. with -> With ] to affect really only the With you want to. This has AFAIS only the disadvantage that you need to be sure that the symbol with is nowhere used in foo for something else. But probably one can come around that with something like Unique. However, this is not necessary for Let, since there is no code evaluated before the expression is build up and the block ends -- no code but transformation code which contains no other With. In your code > ClearAll[LetL]; > SetAttributes[LetL, HoldAll]; > LetL /: > Verbatim[SetDelayed][lhs_, rhs : HoldPattern[LetL[{__}, _]]] := > Block[{With}, > Attributes[With] = {HoldAll}; > lhs := Evaluate[rhs]]; > LetL[{}, expr_] := expr; > LetL[{head_}, expr_] := With[{head}, expr]; > LetL[{head_, tail__}, expr_] := > Block[{With}, > Attributes[With] = {HoldAll}; > With[{head}, Evaluate[LetL[{tail}, expr]]]]; are two things which I probably would like to improve a little bit. First, I don't really like that you start a new Block for each assignment. In my understanding With's are fast but Blocks and especially Modules are slow. I hoped to still get a faster code by using Let[ { a = ..., b = ..., c = ..., ... }, doSomething ] compared to Module[ { a, b, c, ... }, a = ...; b = ...; c = ...; ...; doSomething ] but I'm not sure if this still works when there are n With and n Blocks for n assignments. (I did't tested it.) And second, for the down rule you also build up the whole expression before you start evaluating it. The former way without the block worked more like I would expect it to do from outside to inside. Beside this, I wonder what the HoldPattern before the Let is good for. Should I add it to the code a few lines down, too? I tried to improve this two things. I left the down rule as it was before and implemented a up rule with the Block trick (but only once) which Folds up the whole With expression independent of the down rule: SetAttributes[ Let, HoldAll ] SyntaxInformation[ Let ] := { ArgumentPattern -> { _, _ } } Let[ { h_ , t__ }, x_ ] := With[ { h }, Let[ { t }, x ] ] Let[ { h_ }, x_ ] := With[ { h }, x ] Let[ { }, x_ ] := x Verbatim[ SetDelayed ][ l_, Let[ v_, x_ ] ] ^:= Block[ { With }, SetAttributes[ With, HoldAll ]; l := Evaluate @ ReleaseHold @ Fold[ With[ { #2 }, #1 ] &, Hold @ x, Reverse[ Hold /@ Unevaluated @ v ] ] ] I think the Let is now alredy pretty mature. Can you think of more situations where it might be useful to fold up the Let beside in SetDelayed? I also think about to only use this up rule when there is somewhere a Condition in the Let, but I don't know how to figure that out. Does something like Let[ v_, x : ___ Condition ___ ] match always? > Hope this helps. Yes, it did. Thank you very much. Bastian