What is the easiest way to accomplish the following in a Mathematica clone or in any version of Lisp? Also it doesn't appear in any lisps have a similar replace function.

Replace[arg, f[{x_, "[", y__, "]"}] :> x[y]]

You are welcome to vote to close the same question has been asked at stackoverflow. I'm not going to delete it because I think it is beneficial for search.

  • $\begingroup$ I don't believe questions about Lisp are on-topic here. Why do you feel your question is on-topic? $\endgroup$ – Sjoerd C. de Vries Sep 15 '15 at 19:08
  • $\begingroup$ @SjoerdC.deVries Mathematica clones is own topic(I just included lisp for completion). Do you think I should post it over at stackoverflow then. I'm just afraid it won't get the right attention. $\endgroup$ – William Sep 15 '15 at 19:11
  • 1
    $\begingroup$ stackoverflow with both mathematica and lisp tags. Give some usage examples. $\endgroup$ – george2079 Sep 15 '15 at 19:33
  • 1
    $\begingroup$ @William Clojure has a limited form of destructuring , which is somewhat similar to patterns, although much less general. However, it works pretty well still, for things that are needed in practice, such as bindings for passed arguments or their parts for functions, and the like. $\endgroup$ – Leonid Shifrin Sep 15 '15 at 20:55
  • 1
    $\begingroup$ I'm voting to close this question as off-topic because emulating Mathematica functionality in other programming languages does not fall into the purview of this site. $\endgroup$ – m_goldberg Sep 15 '15 at 22:21

Here is my solution using Mathematica and the package FunctionalParsers.m available at GitHub. This solution might not look very pretty. And used infix notation in order to get shorter code.


varNameParser = 
     StringLength[#] > 0 && StringMatchQ[#, WordCharacter] &]]];

varSequenceParser = ParseListOf[varNameParser, ParseSymbol[","]];

fArgsParser = ParseApply[#[[1]] <> "[" <> Riffle[#[[2]], ","]
     <> "]" &, (varNameParser \[LeftTriangle] 
     ParseSymbol[","] \[RightTriangle] (varSequenceParser)]];

fParser = 
  ParseSymbol["f"] \[RightTriangle] 

fsListParser = 
  ParseCurlyBracketed[ParseListOf[fParser, ParseSymbol[","]]];

The result from applying the last parser, fsListParser, to:

argStr = "{f[{m,[,1,2,3,]}],f[{x,[,y,]}],f[{c,[,a,b,]}]}"

is this:

{{{}, {"m[1,2,3,]", "x[y,]", "c[a,b,]"}}}

I am not sure how satisfying this final result is. I am mostly trying to illustrate the use of Functional Parsers (or parser combinators) for this kind of problem. In short, the parsing recognizes the pattern and the pattern is being acted upon using ParseApply.

Let us look at what the parsers do in turn.

  1. varNameParser -- parsing a sequence of letters and numbers as an entity.

    In[243]:= varNameParser[{"a", "b"}]

    Out[243]= {{{}, "ab"}}

  2. varSequenceParser -- parsing a list of entities.

    Here we get several alternatives of successful parsing. The first one is the one we want.

    In[274]:= varSequenceParser[Characters["ab,1232,x"]]

    Out[274]= {{{}, {"ab", "1232", "x"}}, {{",", "1", "2", "3", "2", ",", "x"}, {"ab"}}, {{"a", "b", ",", "1", "2", "3", "2", ",", "x"}, {}}}

  3. fArgsParser -- parses the internal arguments of f.

    This parser also applies a function to the parsed result using ParseApply. (The comma after "m" shows that my implementation of ParseListOf has a bug.)

    In[275]:= fArgsParser[Characters["x,[,y,m,]"]]

    Out[275]= {{{}, "x[y,m,]"}}

  4. fParser -- parse an instance of f[__] .

    In[234]:= fParser[Characters["f[{x,[,y,]}]"]]

    Out[234]= {{{}, "x[y,]"}}

  5. fsListParser -- parse a list of f terms.

    In[305]:= fsListParser[Characters[argStr]]

    Out[305]= {{{}, {"m[1,2,3,]", "x[y,]", "c[a,b,]"}}}

  6. The output of fsListParser in 5 is a list of strings not a string. If we want a string for the output we can modify fsListParser with ParseApply:

    fsListParser = ParseCurlyBracketed[ ParseApply[ "{" <> StringJoin @@ Riffle[#, ","] <> "}" &, ParseListOf[fParser, ParseSymbol[","]]]];

    Now we obtain a string:

    In[293]:= fsListParser[Characters[argStr]]

    Out[293]= {{{}, "{m[1,2,3,],x[y,],c[a,b,]}"}}

This might seem quite messy. I am not sure is this solution the easiest, but it is quite universal. I find this technique quite powerful.

The package FunctionalParsers.m can generate parsers from BNF specifications. I opted of writing the parsers directly in order to better illustrate the technique. The functional parsers can be relatively easily implemented in any functional language. (I have made implementations in Mathematica, R, and Lua.) Scala has functional parsers included in it. There are packages for C# and Java.

This blog post of mine has explanations and references on functional parsers application: Natural language processing with functional parsers . This presentation has technical details: Functional parsers for an integration requests language .

| improve this answer | |
  • $\begingroup$ Give me a second to read it all. But it appears you have just proposed using a Package. I'm trying to avoid using Mathematica. $\endgroup$ – William Sep 15 '15 at 21:37
  • $\begingroup$ @William I thought I can run that package in Mathics. (Now I don't think so.) Nevertheless, you can use this solution in Scala and Haskel. (They have monadic parsers.) I am sure there are packages for monadic parsers in Lisp -- see github.com/drewc/smug . $\endgroup$ – Anton Antonov Sep 15 '15 at 21:41
  • $\begingroup$ If you know how to do it in lisp I will happily accept the answer. I gave an upvote but it doesn't really answer the question. $\endgroup$ – William Sep 15 '15 at 21:56
  • $\begingroup$ @William Yeah, I am interested to do a Lisp solution. I plan to make one later this week. I provided a Mathematica solution because of the comments to your question, and because I thought it will work with Mathics. Thanks for the up-vote! $\endgroup$ – Anton Antonov Sep 16 '15 at 0:26

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