MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

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


  • Prev by Date: Re: Problem in plotting Bifurcation Diagram (ListPlot with
  • Next by Date: Boundary Value Problem (a correction)
  • Previous by thread: Re: Problem in plotting Bifurcation Diagram (ListPlot with
  • Next by thread: Boundary Value Problem (a correction)