13
$\begingroup$

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?

$\endgroup$
  • 1
    $\begingroup$ I take it you would not find RandomSample[#, 3] &[Range[10]] to be satisfying. In any case, a very good question. $\endgroup$ – bbgodfrey Apr 18 '16 at 5:14
  • 4
    $\begingroup$ How about Infix notation? It looks nice for your example: Range[10]~RandomSample~3. No need to Unprotect anything. $\endgroup$ – Jens Apr 18 '16 at 6:02
  • $\begingroup$ You can find more function run EntityList[EntityClass["WolframLanguageSymbol","Curryable"]] $\endgroup$ – yode Apr 18 '16 at 7:46
  • $\begingroup$ @yode that's a nice feature! $\endgroup$ – M.R. Apr 18 '16 at 8:25
  • $\begingroup$ 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. $\endgroup$ – RunnyKine Apr 18 '16 at 16:01
6
$\begingroup$

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} *)
$\endgroup$
5
$\begingroup$

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}]&).

$\endgroup$
  • 1
    $\begingroup$ 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) $\endgroup$ – Lukas Lang Sep 8 '17 at 16:38

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.