Custom operator form for system functions?

There are some functions for which an operator form would make sense but isn't implemented. For example, I'd like to make this work:

RandomSample[3] @ Range[10]


You can do something like this:

Unprotect[RandomSample]; Off[RandomSample::lrwl]
RandomSample[n_][x_] := RandomSample[x, n]


But I wonder if there is a standard technique to define operator forms for system functions?

• I take it you would not find RandomSample[#, 3] &[Range[10]] to be satisfying. In any case, a very good question. – bbgodfrey Apr 18 '16 at 5:14
• How about Infix notation? It looks nice for your example: Range[10]~RandomSample~3. No need to Unprotect anything. – Jens Apr 18 '16 at 6:02
• You can find more function run EntityList[EntityClass["WolframLanguageSymbol","Curryable"]] – yode Apr 18 '16 at 7:46
• @yode that's a nice feature! – M.R. Apr 18 '16 at 8:25
• The answer to this question is NO. There is no standard way of defining operator forms of a built-in function short of Unprotecting and defining one yourself or hoping that in a future release Wolfram Inc. would include one. – RunnyKine Apr 18 '16 at 16:01

Since there was no objection to my comment, I'll post it as an answer:

By using Infix notation, an operators with arbitrarily many arguments (more than one) can be written as in this example:

Range[10]~RandomSample~3


So the operator separates the arguments in the input.

If, on the other hand, you want to actually use a re-defined version of the built-in operator in your programming, then the answer would be different. A custom operator for a system function can always be defined as below:

randomSample[n_] := Function[list, RandomSample[list, n]]

rs = randomSample[3]

(* ==> Function[list$, RandomSample[list$, 3]] *)

rs[Range[10]]

(* ==> {6, 2, 3} *)

randomSample[3][Range[10]]

(* ==> {8, 2, 10} *)


A true operator would use SubValues but here's a position-coded pseudo-operator form "constructor" using UpValues that can be applied to most or all system functions:

\[Bullet] /: h_[pre___, \[Bullet], post___] :=
Function[expr, h[pre, expr, post]];


For example,

Dataset[{a, b, d, c}][
Partition[\[Bullet], 2] /*
MapIndexed[Rule, \[Bullet], {2}]] // Normal


{{a->{1,1},b->{1,2}},{d->{2,1},c->{2,2}}}

• Could not use SubValues with this definition - too deep for evaluator.

• Position coding enables options or other parameters (only Map and a few other system functions allow this). This is also useful for functions like MemberQ where one might operate on either the first or second slot.

• It uses Bullet because it looks nice and takes only 2 chars to input: Alt-8 (ideally, one should be able to type two commas in a row to represent the desired slot, but overloading Null doesn't work).

• Though it seems it only saves one character compared to #...& Function syntax, it also avoids parentheses when combined with RightComposition as in the above example: ... /* (MapIndexed[Rule,#, {2}]&).

• Very nice! A possible slight improvement: \[Bullet] /: h_[pre___, \[Bullet], post___] := Function[, h[pre, ##, post], {HoldAll}] This allows you to splice in arbitrarily many arguments and also Holds them so that the Hold related attributes of f can kick in (however, both these "features" are not supported for the built-in operator forms, so this might confuse the user) – Lukas Lang Sep 8 '17 at 16:38