# Infix form of PutAppend ( >>> ) does not work with variable

I'm new to Mathematica, so I suspect this question involves either a misunderstanding involving variables or the usage of >>>.

On a webMathematica page (backed by Mathematica 5.2), I have the following:

foo[arg_] := Module[{argN},
ArgN = arg;
filenameS ="Absolute/Path/To/File";
ArgN >>> filenameS; (*Problem Line*)
];
foo["test"];


Running this appears to do nothing. When I replace the line

ArgN >>> filenameS;


with

PutAppend[ArgN, filenameS];


It works perfectly, appending "test" to the file. Why doesn't the infix form of PutAppend work in the same way?

• Also, ArgN >> "Absolute/Path/To/File" works. Puzzling. – cormullion Aug 15 '13 at 8:17

I believe it does work, just not how you expect. :-)

From the documentation for PutAppend:

Note that there are no quotation marks around filename in the first line.
It is not made particularly clear but you can use this syntax with >>>:

Range[10] >>> file.txt


Which outputs to a file named file.txt directly. This is a special and unusual parsing, used also for >> (Put) and << (Get).

Because of this your results are being sent to a file named filenameS rather than one named according to the string value of filenameS.

Usually file.txt would be interpreted as Dot[file, txt], but in the case of >>> it is parsed differently. Here is a low-level look at what is going on. parseString(1) parses as string using the Front End into Box form.

parseString[s_String, prep : (True | False) : True] :=
FrontEndExecute @ FrontEndUndocumentedTestFEParserPacket[s, prep]

"data >>> file.txt" // parseString
"data :> file.txt"  // parseString

{BoxData[RowBox[{"data", ">>>", "file.txt"}]], StandardForm}

{BoxData[RowBox[{"data", ":>", RowBox[{"file", ".", "txt"}]}]], StandardForm}


Note the different handling. Here RuleDelayed was used as an arbitrary "normal" operator.

As further illustration of the special parsing we can demonstrate that neither Function nor With can effect the substitution. This outputs to a file named x rather than myfile.txt:

With[{x = "myfile.txt"},
Range[5] >>> x
]


This isn't even valid input:

(Range[5] >>> #) &["myfile.txt"]


Syntax::sntxf: "(" cannot be followed by "Range[5]>>>#)".

Syntax::tsntxi: "Range[5]>>>#" is incomplete; more input is needed.

Nevertheless we can attempt to override the behavior with \$PreRead or MakeExpression which work at the Box level:

MakeExpression[RowBox[{lhs_, ">>>", rhs_String}], form_] :=
MakeExpression[
RowBox[{"PutAppend", "[", RowBox[{lhs, ",", rhs}], "]"}],
form
] /; ! StringMatchQ[rhs, "\"*\""]


Now any appearance of lhs >>> rhs where rhs is not a string should behave as PutAppend[lhs, rhs], assuming I wrote the rule correctly.

• You can use pathnames if the 'filename' is in quotes: Range[100] >>> "/tmp/wizard.txt"... So there's no way to pass a file or pathname into this >>> syntax? – cormullion Aug 15 '13 at 9:32
• @cormullion (1) Yes. (2) That's correct AFAIK. – Mr.Wizard Aug 15 '13 at 10:59
• Well that's a little annoying... Thanks though. I'll mark as answer in a couple hours (assuming nothing else shows up). – Daniel Aug 15 '13 at 17:21
• @Mr.Wizard Under the documentation for Put, it states that expr >> filename is equivalent to expr >> "filename", and PutAppend is supposed to work the same as Put. Is this just misleading documentation? – Daniel Aug 15 '13 at 18:10
• @Daniel Actually I think that describes the behavior rather well: the point is you can omit the quotation marks and it behaves the same way. Since this behavior displeases you I'll see if I can provide a practical work-around. – Mr.Wizard Aug 15 '13 at 21:40

Mr. Wizard's answer is basically correct. I was originally going to just edit his answer, but I decided this is a bit too much to do that. Mr. Wizard, feel free to delete my answer and just incorporate this info into yours.

There are six special "auto-stringifying" operators, namely:

 >> >>> << :: ? ??


These parse the argument to their right. If the argument is a string, they they will slurp up that whole string. If the argument isn't a string, they will read until they've reached the end of a file name (as defined in Operator Input Forms) for the first three or a symbol for the last 3. This argument is then converted to a string before any evaluation happens. Indeed,

In[38]:= Hold[<< foo] // InputForm
Out[38]//InputForm= Hold[Get["foo"]]


and

In[43]:= foo::bar::English//FullForm
Out[43]//FullForm= MessageName[foo,"bar","English"]


Because this happens deep in the parser (converter of boxes or text to Wolfram Language expressions) before any evaluation happens, there really is no way to change this short of something like the MakeExpression rule proposed by Mr. Wizard. Of course, then something like a >>> myfile.txt will no longer work after that change.

You call always used the head[args] form if you want to use any arbitrary expression. Incidentally, both ? and ?? are different forms of Information.

• Also, there's the weird operators _ __ ___ which, in the front-end, "stringify" stuff directly to the left and right of them, but internally gets parsed into a Pattern[Symbol, Blank[Symbol]]. – QuantumDot Sep 11 '17 at 17:43
• At the risk of being overly pedantic, the underscores are not operators, nor do they stringify any more then Sin stringfiies (if you look at the boxes for Sin[x], you'll see it involves "Sin" and several other strings). What's happening is that they tokenize together with symbol tokens on either side. Then they parse according to the special rules of tokens which have underscores in them, just as if you evaluated ToExpression["f_h"]`. Notice in the above tutorial they are listed in the "special input form" table, not the "operator precedence" table. – Itai Seggev Sep 12 '17 at 6:49