# Writing a function that returns a (usable) function

I am trying to create a function that returns Arnold's Cat Map of size n iterated k times. I can get something out of the Function command, but I can't figure out how to use that output as a function.

The non-iterated version of the problem is trivial. I define my mapping function:

G[x_, y_, n_] := Mod[{{2, 1}, {1, 1}}.{x, y}, n];


I want it to work with ImageTransformation, so I define an appropriate function for that:

CatMapStep[{x_, y_}] := G[x, y, side];


where side is calculated somewhere earlier. Now I can call ImageTransformation (let's say I have an image kitty):

ImageTransformation[kitty, CatMapStep]


Done. But what do I do if you want to iterate CatMap k times? Well, I can hard-code k:

CatMapFiveTimes[u_] := Nest[CatMapStep[u], u, 5];


And I discovered the Function' command, but I can't figure out how to use it. What I would really like to do is create a function that takes k as an argument, and returns a function of u. Such is the sentiment of the following incorrect snippet:

IteratedCatMap[k_] := Function[u, Nest[CatMapStep[u], u, k];   <--- DOESN'T WORK


In my fantasy world, I would then be able to define CatMapFiveTimes by invoking the following line:

CatMapFiveTimes[u_] = IteratedCatMap;     <--- HYPOTHETICAL


And then using it as I would the previous definition.

How can I create this function that returns a function?

Thanks, David

PS: Note that I am using Mathematica 8, although my officemate has Mathematica 9 and she couldn't get it, either.

PPS: I am completely open to a totally different approach to this problem. Ultimately, my only goal is to use Manipulate to let my students specify how many iterations of the cat map they want to see. I will be doing similar things for the Mandelbrot set, as well.

• Define "doesn't work." What happens when you run it? The reason I ask is I've run your code, and I've seen what happens. But, you don't give enough info for the casual reader to know what the issue is. – rcollyer Aug 13 '13 at 1:49
• Related or possible duplicate: (7999) – Mr.Wizard Aug 13 '13 at 17:29

## 2 Answers

Perhaps just a syntax problem:

side = 1;
kitty = ExampleData[{"TestImage", "Lena"}];
G[x_, y_, n_] := Mod[{{2, 1}, {1, 1}}.{x, y}, n];
CatMapStep[{x_, y_}] := G[x, y, side];
CatMapFiveTimes[u_] := Nest[CatMapStep, u, 5];
it5 = ImageTransformation[kitty, CatMapFiveTimes];

IteratedCatMap[k_] := Function[u, Nest[CatMapStep, u, k]];
itt5 = ImageTransformation[kitty, IteratedCatMap];

GraphicsRow@{it5, itt5} • Lena, oh Lena, please accept my apologies! – Dr. belisarius Aug 13 '13 at 3:29
• Damn. Should have noticed that small issue. +1, grudgingly. :) – rcollyer Aug 13 '13 at 13:42
• @rcollyer Ha! Mma always finds a way to get me staring stupidly at a line of code for hours – Dr. belisarius Aug 13 '13 at 13:56
• I had a semi-colon issue once. A single misplaced semi-colon was fubaring about 500 lines of code, and I couldn't find the damn thing. Two syntax highlighters and Mr.Wizard's message tool later, I found it. But, it took much longer than I care to admit to. – rcollyer Aug 13 '13 at 14:09
• This did it! Thank you! – David Bruce Borenstein Aug 14 '13 at 12:48

This question is related to and possibly a duplicate of: Define parameterized function

First there appears to be a mistake in your code; I believe you wanted:

CatMapFiveTimes[u_] := Nest[CatMapStep, u, 5]


To realize your IteratedCatMap we do not need to generate a function, merely to use a SubValues pattern definition (as discussed in the link above).

IteratedCatMap[n_][u_] := NestList[CatMapStep, u, n]


I have used NestList above in place of Nest simply to make the operation of the function visible.

With our supporting definitions in place:

G[x_, y_, n_] := Mod[{{2, 1}, {1, 1}}.{x, y}, n];
CatMapStep[{x_, y_}] := G[x, y, side];
side = Prime @ 50;


To use this you simply write:

IteratedCatMap[{62, 35}]

{{62, 35}, {159, 97}, {186, 27}, {170, 213}, {95, 154}, {115, 20}}  (* five + original *)


You can define your "function" like this:

CatMapThreeTimes = IteratedCatMap;

CatMapThreeTimes[{62, 35}]

{{62, 35}, {159, 97}, {186, 27}, {170, 213}} (* three + original *)


Note that the value of CatMapThreeTimes is not a function, it is simply a head waiting to be completed before the SubValues rule triggers.

You can use Function as also discussed in the linked question:

IteratedCatMapAlt[n_] := NestList[CatMapStep, #, n] &

CatMapTwoTimes = IteratedCatMapAlt;


The value of CatMapTwoTimes is a function (a pure function, specifically).

## Notes

• It is generally a good idea to avoid starting user Symbol names with capital letter, especially short or generic names like G because these may conflict with System Symbols now or in the future.

• Beware creating function that rely on a global definition such as side. It is often better to include such a parameter as an argument, possibly using SubValues as discussed above.

To illustrate the second point you might write your functions like this:

ClearAll["Global*"]

G[side_][{x_, y_}] := Mod[{{2, 1}, {1, 1}}.{x, y}, side]

catMap[side_, n_][u : {_, _}] := Nest[G[side], u, n]


You can then create a particular version of the "function" simply with:

catMap4 = catMap[229, 4];


And use it:

catMap4[{62, 35}]

{95, 154}
`
• Thank you! So would this be more computationally efficient than the Nest approach, because the new function is not actually generated? I don't have a very good sense of how Mathematica evaluates things. The function was actually named \Gamma, but I couldn't paste the Greek letter, so I decided to change it to G. I will keep that in mind about the global parameters. Is there a book on Mathematica programming that's reasonably concise and informative? – David Bruce Borenstein Aug 14 '13 at 12:51
{"ft_lang_label":"__label__en","ft_lang_prob":0.8808114,"math_prob":0.80646014,"size":1741,"snap":"2021-04-2021-17","text_gpt3_token_len":452,"char_repetition_ratio":0.11398964,"word_repetition_ratio":0.033898305,"special_character_ratio":0.2498564,"punctuation_ratio":0.16120219,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9639444,"pos_list":[0,1,2],"im_url_duplicate_count":[null,4,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-04-18T20:43:42Z\",\"WARC-Record-ID\":\"<urn:uuid:5ee49b18-9fb0-4e80-a6b4-e25b56d6a818>\",\"Content-Length\":\"186443\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:5643f897-664d-4a8a-9870-d8289afe676d>\",\"WARC-Concurrent-To\":\"<urn:uuid:2bf1dcf7-7deb-478a-a231-e48eba08ecd9>\",\"WARC-IP-Address\":\"151.101.65.69\",\"WARC-Target-URI\":\"https://mathematica.stackexchange.com/questions/30329/writing-a-function-that-returns-a-usable-function/30332\",\"WARC-Payload-Digest\":\"sha1:BGKDRNRHLLFK7ELSZGW3KUACTO3YWHKT\",\"WARC-Block-Digest\":\"sha1:QCTKWEMGQUHMAXATL7IXVBVHLSFQFQSH\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-17/CC-MAIN-2021-17_segments_1618038860318.63_warc_CC-MAIN-20210418194009-20210418224009-00336.warc.gz\"}"}