MathGroup Archive 2010

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

Search the Archive

Re: Defining UpValues

  • To: mathgroup at smc.vnet.net
  • Subject: [mg110794] Re: Defining UpValues
  • From: Leonid Shifrin <lshifr at gmail.com>
  • Date: Wed, 7 Jul 2010 07:41:02 -0400 (EDT)

Istvan,

Actually in that first letter that I never sent to you I had a solution
which used a wrapper,
so this is how I also would do that. The main problem to overcome in making
your original code work
was that the heads of expressions (even composite heads) evaluate before
anything else (there is a separate
recursion on heads in the case of nested heads), and evaluation of func[sys]
in func[sys][args] is
completely local in the sense that at the time func[sys] is evaluated, the
evaluator has no idea
whether this is a head of a larger expression or a stand-alone expression.

I tried many different things but all of them failed in one way or another,
until I realized that the evaluation stack can provide the non-local
evaluation information
that we needed. It looks like this trick can be used generally when we need
to  divert evaluation
in a way that can not be achieved by the standard evaluation control
(Evaluate, Unevaluated,
Hold-attributes, etc), but one has to have a really good reason to do so!

Best,
Leonid



2010/7/6 Istv=E1n Zachar <replicatorzed at gmail.com>

>  Dear Leonid,
>
> thanks for the answer. Yes, I agree that the design is not the best in this
> case, and to tell you the truth,
> just after posting my question here I've decided - though I was a bit
> dubious about it - to introduce the wrapper.
> Now I'm much more confident with my choice as it seems to be the general
> method to handle situations like this.
>
> The only problem (at the moment) with the wrapper is that previously the
> (IRL) outcome of func was a list, while
> now it has the wrapper as head, making ReplaceAll calls a bit harder to
> implement (like
>
> {a, b} /. Wrapper[a -> 1, b -> 2]
>
> which gives an errormessage. But setting UpValues for Wrapper with
> ReplaceAll does help here:
>
> Wrapper/: ReplaceAll[expr_, rep_Wrapper] :== ReplaceAll[expr, List @@ rep];
>
> Anyway, your solution is impressive in its simplicity: I never would have
> thought to fiddle with the evaluation stack,
> but it's a very clever workaround! Though I won't use it, it still remains
> to be a rather tricky intellectual achievement : )
>
> Istvan
>
>
>
> On 2010.07.06. 14:12, Leonid Shifrin wrote:
>
> Hi Istvan,
>
> This was a tough one. Here is one way (it took me a while to figure it out,
> first I thought it was
> not possible, and almost sent you a long explanation why it is
> impossible))):
>
> ClearAll[func];
> func[x_Integer] :==
>   x /; ! MemberQ[Stack[_], HoldForm[func[_Integer][args___]]];
> func /: func[sys_Integer][args___] :== sys + 1;
> func[sys_Function] :== sys;
>
>
> In[191]:== {func[1], func[1][2], func[# + 2 &], func[# + 2 &][2]}
>
>
> Out[191]== {1, 2, #1 + 2 &, 4}
>
> I would still consider changing the design though, since this kind of
> difficulties / workarounds usually
> indicate to me that the design of the function in question is not well
> thought over. For example, if
> your sys is often supplied with additional optional arguments, you can
> create a wrapper say sysData (or, just
> a List) and store them there, like func[sysData[sys,opts___]], etc.
>
> Hope this helps.
>
> Regards,
> Leonid
>
>
> 2010/7/6 Istv=E1n Zachar <zac at freemail.hu>
>
>> Dear Group,
>>
>> consider the following code:
>>
>> func[sys_Integer] :== sys;
>> func /: func[sys_Integer][args___] :== sys + 1;
>> func[sys_Function] :== sys;
>>
>> {
>>  func[1],
>>  func[1][2],
>>  func[# + 2 &],
>>  func[# + 2 &][2]
>>  }
>>
>> Is there a way to define func such a way that when the main argument
>> is an Integer, any further arguments are ignored? That is, to
>> return:    {1, 2, #1 + 2 &, 4}    instead of    {1, 1[2], #1 + 2 &,
>> 4}. At present, the second function definition is basically ignored by
>> the kernel.
>>
>> I am aware that func[sys_type, args___] would be the easiest way to
>> use here, but in my real code
>>    1. there is a large number of named options supplied with sys
>> preventing (or at least making hard) the use of *any number* of
>> optional second arguments;
>>    2. sometimes the main call (func[sys]) is separated from the
>> introduction of any optional argument (this is part of a GUI), which
>> may cause calls like this:
>>    x == func[some_function]; ... (* calculations involving x *) ... ;
>> y == x[2];
>>
>> Thanks in advance,
>>
>> Istv==E1n
>>
>>
>>
>>
>>
>>


  • Prev by Date: Re: overloading a function name in a package? How to query all names?
  • Next by Date: Re: Defining UpValues
  • Previous by thread: Re: Defining UpValues
  • Next by thread: Re: Defining UpValues