67

Operator Precedence Table Unless one wishes to write in FullForm a competent Mathematica user must be familiar with at least the majority of syntax precedence rules, which are described in the Operator Precedence table. Clarification: I do not mean that one must memorize (most of) this entire table be competent, but rather that one should know it well ...


45

For me the operator forms of Map and Apply will probably provide the most important benefits in terms of code readability. Often I need to apply a sequence of transformations to some data, and I am fond of infix notation for this purpose. For example I find a ~Position~ 0 ~SortBy~ Last more readable than the "conventional" SortBy[Position[a, 0], Last] ...


38

I would have liked to have more experience with the operator forms before this question was asked as I am short on examples, and I'm sure my opinion will evolve over time. Nevertheless I think I have enough familiarity with similar syntax to provide some useful comments. Taliesin Beynon provided some background for this functionality in Chat: Operator ...


33

Edit: version 11.0 update. Now it is superset of TypeSystem`$OperatorForms. It now also includes operator forms that have different names than the functions they're currying, like EqualTo. One can find these functions in the documentation by keywords "operator form" Select[Names@"*", StringMatchQ[ToString@ToExpression[# <> "::usage"], "*operator ...


29

Maybe I miss the point here, but FullForm[x ↗ y] gives UpperRightArrow[x,y]. This is described in the documentation to UpperRightArrow and since this symbol is not protected and has not built-in meaning, you can just define it the way you like: UpperRightArrow[x_, y_] := FooBar[x, y] and this instantly gives you Update: As answer to Jacobs comment I ...


24

I find the value of the new operator forms becomes critical when working with datasets. Consider titanic = ExampleData[{"Dataset", "Titanic"}]; titanic[Count[#], "survived"] & /@ {True, False, _Missing} {500, 809, 0} Derive a data set for analyzing the survival of very young passengers. cutoff = 8; youngest = titanic[All, {"age", "survived"}][Select[#...


22

There is a global variable that purports to contain a list of operator forms, TypeSystem`$OperatorForms. I say "purports", because the list is missing some of the forms found by @ybeltukov's method. But to its credit, it correctly identifies the operator form of ReplaceAll which is mentioned in neither a usage message nor the documentation, and also ...


22

From version 10.3 you can use WolframLanguageData. WolframLanguageData[EntityClass["WolframLanguageSymbol", "Curryable"]] As of 11.0, this appears to be the most reliable solution: Unfortunately, this method is not perfect either: at least TuringMachine is missing from it. Hope this helps.


20

You can use any built in operator modified with subscripts, superscripts, etc, and retain its precedence, for your own purposes. For example, say you want a general Apply operator like @@ that could work at any level. One could use create the operator @@ with a number subscripted for the level of Apply seems appropriate MakeExpression[RowBox[{fun_, ...


20

I can't answer how the association is made for the built-in operators, but I can show how to add your own. If your symbol is already an operator you can do this simply as halirutan showed. This question may be a duplicate of How can one define an infix operator with an arbitrary unicode character? but since it admits a simpler interpretation I shall not ...


20

To my knowledge, there aren't built-in versions for comparison operators that would be automatically threaded over lists. One reason for that is that Mathematica is a symbolic system, and every auto-simplification has a cost, because there may be cases when this isn't desirable. It is relatively easy however to construct the behavior you want: ClearAll[l]; ...


20

The definition used (motivated by exterior calculus) is as follows: Given a rectangular array $a$ of depth $n$, with dimensions $\{d, ..., d\}$ (so there are $n$ $d$'s) and a list $x = \{x_1, ..., x_d\}$ of variables, then Curl[a, x] == (-1)^n (n+1) HodgeDual[Grad[a, x], d] If $a$ has depth $n$, then Grad[a, x] has depth $n+1$, and therefore HodgeDual[...


18

If you are looking for complete answer, take a look at Mr. Wizard's :) Also, see the comments of @JacobAkkerboom below, who proved I was too hasty. :) I was right that the function OP is asking about at the end is Precedence but I was wrong in my interpretation of what is happening. I will leave this for future visitors as it is not so obvious. Also, ...


18

Intermingling Operator Forms & Linguistic Connections This answer attempts to draw out linguistic connections in understanding why operator forms seem so useful, a process that can perhaps point to further utility. Operator Forms are a type of modularization with the standard re-use and combinatory advantages but IMO the biggest benefit is cognitive - ...


18

The documentation for Minus states that -x is converted to Times[-1,x] on input. So -Sequence[a,b] == Times[-1,Sequence[a,b]] == Times[-1,a,b] by this definition. Similarly the documentation for Divide states that x/y is converted to x y^-1 on input. and therefore x / Sequence[a,b] == x Sequence[a,b]^-1. Sequence[a,b]^c == Power[a, Power[b,c]]. When ...


17

Update I've created a paclet. Install with: PacletInstall["https://github.com/carlwoll/DifferentialOperator/releases/download/0.1/DifferentialOperator-0.0.1.paclet"] and load with: <<DifferentialOperator` Original post Here's an approach I've been playing with that attempts to mimic traditional notation for these kinds of operators. The ...


17

x/## & // FullForm Function[Times[x,Power[SlotSequence[1],-1]]] and Power[a,b,c...] == Power[a, Power[b, c...]] so now it should be clear. This syntax is mentioned in the last bullet point in details of Power documentation.


17

When using Set rather than SetDelayed you will need to hang the Condition on the left-hand-side: ClearAll[f] f[x_] /; x > 0 = Sqrt[x] f[2] f[-2] Sqrt[x] Sqrt[2] f[-2] There are other reasons to prefer this placement; see: Placement of Condition /; expressions However be aware that the use of Set results in "pre-evaluation" of the RHS which often ...


17

The BoolEval` package does exactly this. For example: BoolEval[{0.6, 1.2} > 1] (* Out: {0, 1} *) and BoolEval[{{0.6, 1.2}, {5, 0.1}} > 1] (* Out: {{0, 1}, {1, 0}} *) In order to return True and False instead of 0 and 1, you can append /. {0 -> False, 1 -> True}.


17

g[f_][x_?NumericQ] := If[EvenQ@Floor[x], f@FractionalPart[x], 1/f@FractionalPart[x]] The ?NumericQ part is important because EvenQ returns False immediately for anything that is not a number. In this case, f needs to be an actual function. Sin[x] and Sin[x]+2 are not functions. They are expressions in terms of x. Sin and Sin[#]+2& are functions. Look ...


15

The Notation package is the most convenient way to define new notation(s). <<Notation` Define an infix notation. You can use the palette that the 'Notation` package pops up to do this. InfixNotation[ParsedBoxWrapper["\[UpperRightArrow]"], FooBar] Check that the infix notation maps to the correct FullForm expression. x \[UpperRightArrow] y // ...


14

Very nice answers. I wanted to add something else. One typical "Mathematica way" of coding involves overloading a function with several definitions, that do different things according to what arguments are passed (I actually abuse this). You can pattern match by head with things like f[x_Integer]:=... and f[x_Real]:=.... I see the Dataset/Query ...


14

The definition of the scalar product in your question assumes that all your kets are orthogonal unit vectors. In that case, the most natural approach would be to use the built-in Bra and Ket as follows: Ket /: Dot[Bra[x__], Ket[y__]] := Times @@ MapThread[KroneckerDelta, {{x}, {y}}] BraKet[x_, y_] := Bra[x].Ket[y] Bra[2, 4].Ket[2, 4] (* ==> 1 *) ...


13

It's not a bug if you consider this behavior as a logical continuation of the following permissible syntax: D[a + b x^3, x, x, x] (* ==> 6 b *) D[a + b x^3, x, x] (* ==> 6 b x *) D[a + b x^3, x] (* ==> 3 b x^2 *) D[a + b x^3] (* ==> a + b x^3 *) The point is that a Sequence of variables is allowed following the first argument of D. And ...


13

If they changed it, I'm pretty sure it would break some code somewhere, possibly in an obscure and hard to debug way. So it's a good thing that they didn't change it. Why does the one argument behaviour make sense? Take a look at the 4th signature in the documentation: Take[list, seq1, seq2, ...] gives a nested list in which elements specified by seq_i ...


13

This can be done with Nest: abderiv[n_] = Function[f, Nest[(a[x] D[#, x] + b[x]) &, f, n]]; abderiv[0][f[x]] (* ==> f[x] *) abderiv[1][f[x]] (* ==> b[x] + a[x] Derivative[1][f][x] *) abderiv[2][f[x]] (* ==> b[x] + a[x] (Derivative[1][b][x] + Derivative[1][a][x] Derivative[1][f][x] + a[x] (f^\[Prime]\[Prime])[x]) *) Here the ...


13

It should be this: lap = D[#, {r, 2}] + 1/r D[#, r] &; lapsquared = lap @* lap; lapsquared[f[r]] // Simplify Or using Laplacian to define lap lap = Laplacian[#, {r, θ}, "Polar"] &;


12

This perhaps: Function[{a, b}, a[#]/b[#] &] @@@ {{a, b}, {c, d}, {e, f}} (* Out: {a[#1]/b[#1] &, c[#1]/d[#1] &, e[#1]/f[#1] &} *) Mr.Wizard's way of writing it (see comment) looks like this in the frontend:


12

Both Operate and Curry don't have access to the full expression, acting mostly on the head. This is why both of them take the depth as an optional argument, to know where to stop, since there is no other way for them to know - their modus operandi is limited to a single interation of evaluation sequence. What you can do is something like this: curry[expr_, ...


12

It comes down to being consistent with the convention/idiom/pattern of WL functions typically having as a first argument an object to be operated on with typically the second argument doing the operating. Operator forms, in contrast, most naturally take as a first argument the thing doing the operating which is therefore most commonly the original function's ...


Only top voted, non community-wiki answers of a minimum length are eligible