11
$\begingroup$

In version 10 some built-in symbols are updated to support operator form like the Derivative. For example, Select, Cases, MatchQ, Map-related functions, and so on. These updates are handy (although it is not clear whether they are directly defined as SubValues for the symbols or defined as functions, see this answer.)

In principle we can check all the new symbols listed here to see which of them have operator form. But this is tedious. Is there a way to automatically return such symbols from Names["System`*"]? The difficulty is, neither DownValues nor SubValues can be used to built-in symbols to return useful information.

$\endgroup$
5
  • 1
    $\begingroup$ It is not only functions (Symbols) introduced in version 10 that may have operator forms; very old functions like Map do too. I do not know how to check a Symbol for such a syntax directly and I fear that the documentation is not consistent enough to use detection of the phrase "operator form" for robust determination. $\endgroup$
    – Mr.Wizard
    Commented May 21, 2015 at 16:56
  • $\begingroup$ @Mr.Wizard, I will be glad to know any possible method that can do this. However I am also glad to know that this is not feasible by using the Wolfram Language alone without help from "external intelligence" (i.e., manual check). In fact the latter case would be a good example for the Godel's incomplete theorem, which states that any consistent system that is general enough to include elementary arithmetic is not complete. I.e., there are always true statements not provable from within such consistent system. To prove these statements we need "external intelligence" outside from the system. $\endgroup$
    – saturasl
    Commented May 21, 2015 at 17:29
  • 1
    $\begingroup$ Note that you could conceivably use SyntaxInformation on Names["System`*"] and then check which of the function that allow a single-argument spec return unevaluated (i.e. in an operator form) without a message when given a single argument, like Map[#&] does now. $\endgroup$
    – Stefan R
    Commented May 21, 2015 at 19:39
  • 3
    $\begingroup$ @Stefan That assumes that all operator forms have a single parameter when in fact they do not; for example: Insert[elem,pos] represents an operator form of Insert that can be applied to an expression. and MapAt[f,pos] represents an operator form of MapAt that can be applied to an expression. $\endgroup$
    – Mr.Wizard
    Commented May 22, 2015 at 8:46
  • 5
    $\begingroup$ Related: mathematica.stackexchange.com/questions/60045/… $\endgroup$
    – Michael E2
    Commented Dec 27, 2015 at 1:23

2 Answers 2

9
$\begingroup$

My own documentation-based approach using usage messages:

file = FileNameJoin[{$InstallationDirectory, "SystemFiles", "Kernel", 
        "TextResources", $Language, "Usage.m"}];

usage = Import[file, "HeldExpressions"];

usage //
  Cases[
    HoldPattern[
      _[_[sym_Symbol, "usage"] = _String?(StringContainsQ["operator form"])]
    ] :> sym
  ]

Output:

{AllTrue, AnyTrue, Append, Apply, AssociationMap, Cases, CellularAutomaton,
CountDistinctBy, CountsBy, Count, DeleteCases, DeleteDuplicatesBy, Delete, Extract,
FirstCase, FirstPosition, FreeQ, GroupBy, Insert, KeyDrop, KeyExistsQ, KeyMap, KeySelect,
KeySortBy, KeyTake, KeyValueMap, Lookup, MapAt, MapIndexed, Map, MatchQ, MaximalBy,
MemberQ, Merge, MinimalBy, NoneTrue, Position, Prepend, ReplacePart, Replace, Scan,
SelectFirst, Select, SortBy, StringCases, StringContainsQ, StringDelete, StringEndsQ,
StringStartsQ, TakeLargestBy, TakeLargest, TakeSmallestBy, TakeSmallest}

This returns fewer items than Michael's method which also includes:

{Dataset, NDSolve, NDSolveValue, Query}

Michael notes that NDSolve and NDSolveValue are false-positives and I would argue that Dataset and Query are special cases so I guess my output is as good as we have so far.

$\endgroup$
7
  • $\begingroup$ +1. Those middle two missing items don't really count. Or rather, it's better that they are omitted. $\endgroup$
    – Michael E2
    Commented May 21, 2015 at 18:50
  • $\begingroup$ @MichaelE2 I was just checking the complement and I conclude that they are all reasonable omissions, so usage messages seem a good start. Now, are there any known operator forms that are missing from this list? $\endgroup$
    – Mr.Wizard
    Commented May 21, 2015 at 18:54
  • $\begingroup$ None that I can spot, but that's not saying much. What's missing is the fault of WRI: Take, Drop, perhaps others that haven't been implemented. (Note Take[list] returns list, but why is that behavior worth saving? Maybe because of Take[list, seq1, seq2],...] I suppose.) $\endgroup$
    – Michael E2
    Commented May 21, 2015 at 19:06
  • $\begingroup$ @Mr.Wizard As always I learn useful knowledge from you, concise yet rich when digested. Thank you for your attention. $\endgroup$
    – saturasl
    Commented May 22, 2015 at 5:41
  • $\begingroup$ @saturasl Thanks for the Accept. If I discover any that are missing from this list I shall try to remember to add them. $\endgroup$
    – Mr.Wizard
    Commented May 22, 2015 at 8:47
12
$\begingroup$

As Mr.Wizard already noted, it's not clear whether "operator form" occurs in the documentation of every command that has an operator form (or conversely, e.g., NDSolve*, which references the operator form of Inactive).

docdir = FileNameJoin[{$InstallationDirectory, "Documentation", 
    "English", "System", "ReferencePages", "Symbols"}];
docs = FileNames["*", docdir];

ops = Count[Get[#], 
    s_String /; StringMatchQ[s, ___ ~~ "operator form" ~~ ___], 
    Infinity] & /@ docs

ToExpression @ Pick[StringDrop[#, -3] & /@ FileNameTake /@ docs, Unitize[ops], 1]
(*
{AllTrue, AnyTrue, Append, Apply, AssociationMap, Cases, \
CellularAutomaton, CountDistinctBy, Count, CountsBy, Dataset, \
DeleteCases, DeleteDuplicatesBy, Delete, Extract, FirstCase, \
FirstPosition, FreeQ, GroupBy, Insert, KeyDrop, KeyExistsQ, KeyMap, \
KeySelect, KeySortBy, KeyTake, KeyValueMap, Lookup, MapAt, \
MapIndexed, Map, MatchQ, MaximalBy, MemberQ, Merge, MinimalBy, \
NDSolve, NDSolveValue, NoneTrue, Position, Prepend, Query, Replace, \
ReplacePart, Scan, SelectFirst, Select, SortBy, StringCases, \
StringContainsQ, StringDelete, StringEndsQ, StringStartsQ, \
TakeLargestBy, TakeLargest, TakeSmallestBy, TakeSmallest}
*)

On a Unix system, you can do this:

commandstring = "!cd " <> docdir <> "; fgrep -l \"operator form\" *";
StringDrop[#, -3] & /@ Import[commandstring, "List"] // ToExpression
$\endgroup$
5
  • $\begingroup$ For what it's worth StringContainsQ is a slightly cleaner method. (+1) $\endgroup$
    – Mr.Wizard
    Commented May 21, 2015 at 18:47
  • $\begingroup$ @Mr.Wizard Oh my, so many new String*Q commands. Looks like they forgot StringContainsExactlyOnceQ. Oh well. (As a string version of MemberQ, I approve, in fact. Should have called it StringMemberQ, though, imo.) $\endgroup$
    – Michael E2
    Commented May 21, 2015 at 18:57
  • $\begingroup$ Funny, I also thought it should have been StringMemberQ for consistency. $\endgroup$
    – Mr.Wizard
    Commented May 21, 2015 at 18:58
  • $\begingroup$ @Michael E2 Brilliant! We let Mathematica examine its own documentation as external sources and search for the key word. I would have considered using python for this, but your alternative script is even better, because it shows the potential to use Wolfram Language to do big things in scientific computing, which for now is still domanined by python together with C++. The first answer clearly attributes to you, while the improved answer from Mr.Wizard can offer better performance and accuracy. For this reason I mark Mr.Wizard's answer as the best answer, but you have my sincere thanks. $\endgroup$
    – saturasl
    Commented May 22, 2015 at 5:29
  • $\begingroup$ @saturasl Thanks & you're welcome. I was hoping you would accept Mr.Wizard's answer, as I think it is better, too. $\endgroup$
    – Michael E2
    Commented May 22, 2015 at 9:54

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