11
$\begingroup$

Often I want a version of @ that is left-associative (might not be using that term correctly).

What I mean is I'd like some operator l@ such that:

a l@ b l@ c === a[b][c]

Standard @ gives us:

a @ b @ c === a[b[c]]

Is there such an operator I've overlooked? (I don't want to use brackets on brackets on brackets)

$\endgroup$
  • 2
    $\begingroup$ Related: mathematica.stackexchange.com/q/11908/403 $\endgroup$ – M.R. Jan 23 at 6:54
  • 1
    $\begingroup$ Also: mathematica.stackexchange.com/q/6355/403 $\endgroup$ – M.R. Jan 23 at 6:55
  • 1
    $\begingroup$ Interesting question, can it be that the documentation is wrong for Infix? According to documentation something like Infix[ f[a,b,c], "~", 490, Left ] is supposed to word but does not. The same syntax should also work for Prefix. $\endgroup$ – gwr Jan 23 at 10:19
  • 1
    $\begingroup$ Being pedantic, the title of the question isn't strictly correct: Apply is @@, not @. The operators @ and // are both called "function application" in the Docs. So more correct title would be "Function application with left-associative grouping". $\endgroup$ – Alexey Popkov Feb 11 at 11:02
11
$\begingroup$

I am not aware of a built-in operator that will call a function with individual sub-value arguments (i.e. curried arguments).

The function Curry has a promising-sounding name, but it lifts a function that takes uncurried arguments into one that takes curried arguments -- sort of the opposite of what we want here.

We could define our own by pressing one of the operators without built-in meanings into service. Let's use CirclePlus () in one of the following ways:

CirclePlus[f_, r___] := Fold[Construct, f, {r}]

or prior to version 11.3:

CirclePlus[f_, r___] := Fold[#[#2]&, f, {r}]

or using the now undocumented function HeadCompose:

CirclePlus = HeadCompose;

With any of these, we can then write:

f⊕a

(* f[a] *)

f⊕a⊕b

(* f[a][b] *)

f⊕a⊕b⊕c

(* f[a][b][c] *)

f⊕a⊕b⊕c⊕d

(* f[a][b][c][d] *)
$\endgroup$
  • $\begingroup$ As I noted in a comment to Carl Woll the issue is that I can't trust these operator forms to not have rules attached to them by someone else. I don't like to play with "System`" level symbols since I can't scope them without potentially breaking someone else's code. What I had to do, inefficient though it is, was to simply attach a DownValue to my primary object that took a pattern like a["method"[]@["property"]] and rewrite it as a["method[]]@"property". As long as I use strings for method and property names there's no danger with premature evaluation here. $\endgroup$ – b3m2a1 Sep 13 at 23:01
  • $\begingroup$ @b3m2a1 I'm inclined to agree with you about overloading the operator forms. It is a powerful tool for project work... but use in library code is downright dangerous. $\endgroup$ – WReach Sep 13 at 23:29
10
$\begingroup$

Another alternative is to use a built-in operator form that has left-associative grouping. A couple examples:

CircleMinus[a_, b_] := a[b]
a ⊖ b ⊖ c

a[b][c]

LeftTee[a_, b_] := a[b]
a ⊣ b ⊣ c

a[b][c]

$\endgroup$
  • $\begingroup$ Thank you! I have been looking for a left-associative operator for a long time! I suppose that in order to fully emulate parsing behavior of @, it would be a good idea to add HoldAllComplete as well. Compare with and without HoldAllComplete: a[b] = HoldComplete; c = 1; a\[CircleMinus]b\[CircleMinus]c $\endgroup$ – Anton.Sakovich Jan 24 at 8:13
  • $\begingroup$ I'm always uncomfortable using these built-in operators because I don't want to take one out of commission for other people... On the other hand I can't just use my own symbol and attach a MakeBoxes rule to it because this needs to work inside a package -_- It's just too dangerous, though, to use one of these "System`" level ones since there's no way to scope its effect. $\endgroup$ – b3m2a1 Sep 13 at 23:00
  • $\begingroup$ @b3m2a1 Would having an input alias work for you? Or does it have to be InputForm only because it's in a package? $\endgroup$ – Carl Woll Sep 17 at 0:22
  • $\begingroup$ It would be used in a package unfortunately. Realistically no one else will ever use it, probably, but I’d like to adhere to good development practices despite that. $\endgroup$ – b3m2a1 Sep 17 at 0:24

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.