0

I am trying to go through this Wolfram Blog example: http://blog.wolfram.com/2009/02/12/flag-analysis-with-mathematica/ on country flag analysis.

I am having a problem understanding the following piece of code:

countryColors =
  (# -> Catch[Intersection[
          StringSplit[
           If[Head[#] === Missing, Throw[""], #]& @
            CountryData[#, "FlagDescription"]],
          colorNames]]) & /@ CountryData[];

where colorNames is just a list of colors.

I do not understand &@ in the above piece of code. What I know is that & is used to define a pure function, and @ is used as a Prefix.

If, for example, the If yields true, then it returns a country name. What does it mean to have &@ after that?

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
Jonas
  • 123
  • 5
  • 1
    f[#]&@a works like f[a]. Here a is CountryData[.... – Kuba Jun 08 '14 at 18:36
  • The question is well posed, but the solution is easily found, so I am voting to close. – Yves Klett Jun 08 '14 at 19:23
  • @YvesKlett - you give an answer and then vote to close? hmm – eldo Jun 08 '14 at 19:26
  • @eldo the intension was to help the OP, regardless of (potential) closure. Related: http://meta.mathematica.stackexchange.com/q/1101. Now that three answers have appeared, others might vote for leaving open in any case. – Yves Klett Jun 08 '14 at 19:34
  • @YvesKlett - yes, probably one should close this, because the code gives utterly wrong answers. – eldo Jun 08 '14 at 19:39

3 Answers3

4

Perhaps it will be easier to understand if I rewrite rgthe blog code in a more step-by-step but less efficient way.

colorNames = {"red", "white", "blue", "green", "yellow", "black"};
flagColors[countryName_] :=
  Module[{description},
    description = CountryData[countryName, "FlagDescription"];
    If[Head[description] === Missing,
      {""},
      Intersection[StringSplit[description], colorNames]]]
countryColors =
  Module[{countryNames, colors},
   countryNames = CountryData[];
   colors = flagColors /@ countryNames;
   MapThread[Rule, {countryNames, colors}]]
{"Afghanistan" -> {"black", "red", "white"}, 
 "Albania" -> {"black", "red"}, 
 "Algeria" -> {"green", "red"}, 
 "AmericanSamoa" -> {"red", "white"},
 ...
 "WesternSahara" -> {""}, 
 "Yemen" -> {"green", "red", "white"}, 
 "Zambia" -> {"green", "red"}, 
 "Zimbabwe" -> {"black", "green", "red", "white", "yellow"}}

There is a bug in the above code because

flagColors["UnitedStates"]
{"blue", "red"}

This is caused by the Intersection expression rejecting "white," and "white;" -- the only instances where white shows up in the flag description. This flaw is also found in the blog code.

m_goldberg
  • 107,779
  • 16
  • 103
  • 257
2

First of all, you have to precede the code example with

colorNames = ToLowerCase[First /@ ColorData["Legacy", "ColorRules"]];

to make it understandable and executable.

You can then define:

FlagColors[x_] := x -> (Intersection[StringSplit["" /@ CountryData[x, "FlagDescription"]], 
   colorNames]) // Quiet

to obtain with

FlagColors /@ CountryData[]

the desired result

I find the author's code rather obscure. Instead of defining a separate function like FlagColors he plugged it with &@ as a pure function into his code making it nearly unreadable.

Aside from this, the author produces wrong answers (f.e., the flag of Bulgaria is not white but white-green-red).

eldo
  • 67,911
  • 5
  • 60
  • 168
0

You already had all blocks in place. & denotes a pure function, and @ is used for prefix notation. As stated by @Kuba, f[#]&@x is basically equivalent to f[x].

Some subtleties on pre- and postfix are discussed e.g. here and here.

One reason for using (or ending up using) this syntax may be that you can easily switcht to a list of arguments together with Map (e.g. f[#]&/@{x1,x2,x3}).

Yves Klett
  • 15,383
  • 5
  • 57
  • 124