8
$\begingroup$

I am trying to use --> operator with highest precedence

Unprotect[LongRightArrow];
LongRightArrow[obj_,property_]:=obj[ToString[property]];
Protect[LongRightArrow];

With this I can do basic operations like accessing properties of an association

In:=  obj = <|"a" -> {2, 3}, "b" -> 5|>
Out:= <|"a" -> {2, 3}, "b" -> 5|>
In:=  obj⟶a
Out:= {2, 3}

However when I try to access elements of list in obj-->a Part takes higher precedence. Same applies for operator ^.

In:=  obj⟶a[[1]]
Out:= Missing["KeyAbsent", "a[[1]]"]
In:=  obj⟶a^2
Out:= Missing["KeyAbsent", "2 a"]
$\endgroup$
  • $\begingroup$ LongRightArrow doesn't have any built in precedence, according to reference.wolfram.com/language/tutorial/OperatorInputForms.html. You might be able to use reference.wolfram.com/language/ref/PrecedenceForm.html $\endgroup$ – evanb Mar 21 '17 at 12:37
  • 1
    $\begingroup$ what should obj-->Part[a,1] do? $\endgroup$ – george2079 Mar 21 '17 at 12:50
  • $\begingroup$ not should but I want to change precedence such that it returns 2, (without affect other operations) $\endgroup$ – Neel Basu Mar 21 '17 at 13:12
  • $\begingroup$ Do you mean you want obj-->a[[1]] to be interpreted as Part[obj-->a,1] and not obj-->Part[a,1] ? Or do you actually want obj-->Part[a,1] to give 2? @george2079 I think if he is talking about precedence he means the first. $\endgroup$ – rhermans Mar 21 '17 at 13:22
  • $\begingroup$ Yes I want the first one. $\endgroup$ – Neel Basu Mar 21 '17 at 13:29
10
$\begingroup$

How about overloading the LongRightArrow with a special rule for Part[...] as the second argument?

Unprotect[LongRightArrow];
SetAttributes[LongRightArrow, HoldRest]
LongRightArrow[obj_, property_] := obj[ToString[property]];
LongRightArrow[obj_, Part[property_, partspec__]] := 
Part[LongRightArrow[obj, property], partspec];
Protect[LongRightArrow];
obj = <|"a" -> {2, 3}, "b" -> 5|>
obj⟶a
obj⟶a[[1]]
<|"a" -> {2, 3}, "b" -> 5|>
{2, 3}
2

Chip Hurst was quicker than I to show the generalization

LongRightArrow[obj_, head_[f_, args__]] := head[LongRightArrow[obj, f], args]

So I'll just take one more step to handle unary postfix operators, such as ! (Factorial). Trivial by replacing args__ with args___:

LongRightArrow[obj_, head_[f_, args___]] := head[LongRightArrow[obj, f], args]

Now

obj⟶a!
{2, 6}

EDIT
Re the comment:

obj⟶a⟶b

is equivalent to

LongRightArrow[obj, a, b]

while the desired behavior is

LongRightArrow[LongRightArrow[obj, a], b]

Well, obviously, that's exactly what we should tell Mathematica, it can't guess that for us.

LongRightArrow[obj_, a_, b__] := LongRightArrow[LongRightArrow[obj, a], b]
obj⟶a⟶b⟶b⟶b⟶b⟶b
 (((((obj⟶a)⟶b)⟶b)⟶b)⟶b)⟶b
$\endgroup$
  • $\begingroup$ But this is not generic what about operator^ ? $\endgroup$ – Neel Basu Mar 21 '17 at 13:56
  • $\begingroup$ @Neel True. Replace Part with a named pattern. I'll add an example once back at the computer. $\endgroup$ – LLlAMnYP Mar 21 '17 at 14:05
  • $\begingroup$ Thanks, This works fine. However what about obj-->x-->y ? Now it works only if I bracket (obj-->x)-->y $\endgroup$ – Neel Basu Mar 30 '17 at 10:46
  • $\begingroup$ @NeelBasu what do you expect from that expression? Its FullForm is LongRightArrow[obj, a, b]; you never proposed a rule for that in the first place. $\endgroup$ – LLlAMnYP Mar 30 '17 at 11:30
  • $\begingroup$ obj-->x-->y to be evaluated as (obj-->x)-->y $\endgroup$ – Neel Basu Mar 30 '17 at 13:04
8
$\begingroup$

You could give LongRightArrow a HoldRest attribute and manipulate the right hand side.

Perhaps something like:

SetAttributes[LongRightArrow, HoldRest]

LongRightArrow[obj_, head_[f_, args__]] := head[LongRightArrow[obj, f], args]

LongRightArrow[obj_, f_] := obj[ToString[f]]

Test:

obj⟶a
{2, 3}
obj⟶a[[1]]
2
obj⟶a^2
{4, 9}
$\endgroup$
  • $\begingroup$ Looks like my answer near-verbatim ;-) $\endgroup$ – LLlAMnYP Mar 21 '17 at 14:28
  • $\begingroup$ @LLlAMnYP Ah, I didn't see your answer until now... $\endgroup$ – Chip Hurst Mar 21 '17 at 14:33
  • $\begingroup$ Well now we have somewhat complementary answers. +1 $\endgroup$ – LLlAMnYP Mar 21 '17 at 14:40
7
$\begingroup$

The precedence of LongRightArrow is predetermined as shown in the operator table. You can attempt to circumvent the problem as other answers show but these do not change the binding power of the operator itself.

As you can see from the table Part has especially high binding power. What you want therefore goes against the design of Mathematica in some way; one would expect obj⟶(a[[1]]) rather than (obj⟶a)[[1]].

If you want to supersede Part you might consider something with natively higher binding power though there aren't many choices; Overscript is one:

Overscript[obj_, property_] := obj[ToString[property]];

Now entered using Ctrl+7:

enter image description here

Manually parenthesizing i.e. actually writing (obj⟶a)[[1]] is another option:

(obj⟶a)[[1]]
2

Note: you do not need to Unprotect Overscript or LongRightArrow as these operators are intended for use.

$\endgroup$
  • $\begingroup$ Good catch about the absence of a Protected attribute. +1 $\endgroup$ – LLlAMnYP Mar 21 '17 at 15:27
3
$\begingroup$

If you don't mind mucking with the internal file UnicodeCharacters.tr (make a copy first!) you can change the line:

0x27F6 ⟶ ($-->$ $&LongRightArrow;$ $\longrightarrow$) Infix   650 None    2   2

to:

0x27F6 ⟶ ($-->$ $&LongRightArrow;$ $\longrightarrow$) Infix   750 Left    2   2

and then close and relaunch Mathematica so that the changes take affect. Afterwards I get:

obj⟶a[[1]]

2

and:

obj⟶a^2

{4, 9}

Also, the grouping change means:

obj⟶a⟶b //Hold //FullForm

Hold[LongRightArrow[LongRightArrow[obj,a],b]]

gets parsed the way you want.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.