Constructing a a family of anonymous functions by recursion.

1 回表示 (過去 30 日間)
Leo Simon
Leo Simon 2016 年 10 月 12 日
コメント済み: Guillaume 2016 年 10 月 12 日
I'm trying to define a sequence of functions recursively. The example below (which is obviously silly) illustrates the idea, which is to construct
f{:} such that
f{i}(x) = f{ii-1}(x)^2
The problem with the code below is that
f{3} = f{2} = @(x)RecursiveFun(x,f{ii-1})
whereas I want
f{2} = @(x)RecursiveFun(x,f{1})
f{3} = @(x)RecursiveFun(x,f{2})
In short, for some reason matlab is not substituting in the passed value of ii.
Obviously I can accomplish what I want by creating a loop of strings and eval'ing each string to create the desired anonymous functions, but everybody on this forum always says not to use eval's.
Thanks for any help!
Here's the code
f{1} = @(x) x^2;
Recursivefun = @(x,F) F(x)^2;
for ii=2:3;
f{ii} = @(x) RecursiveFun(x,f{ii-1});
end;
disp(['f{2}=']);
f{2}
disp(['f{3}=']);
f{3}

採用された回答

Guillaume
Guillaume 2016 年 10 月 12 日
編集済み: Guillaume 2016 年 10 月 12 日
Be careful that matlab is case sensitive, you have Recursivefun and RecursiveFun.
Your code works. Yes, matlab has not replaced the ii by its actual value, but the value of ii is actually embedded in the anonymous function (anonymous functions are closure). So for f{3}, the value of ii is fixed at 3 (and you can't actually change it after the declaration), and for f{2}, the value of ii is fixed at 2.
You can actually check that:
>> metafn = functions(f{3})
metafn =
struct with fields:
function: '@(x)RecursiveFun(x,f{ii-1})'
type: 'anonymous'
file: ''
workspace: {[1×1 struct]}
within_file_path: '__base_function'
>> metafn.workspace{1}
ans =
struct with fields:
RecursiveFun: @(x,F)F(x)^2
f: {@(x)x^2 @(x)RecursiveFun(x,f{ii-1})}
ii: 3
>> metafn = functions(f{2});
>> metafn.workspace{1}.ii
ans =
2
And your function actually produces the correct result:
>>f{3}(2)
ans =
256
The only way to get the index value explicitly embedded in the function code is with the dreaded eval:
for ii = 2:3
f{ii} = eval(sprintf('@(x)RecursiveFun(x,f{%d})', ii-1));
end
but as explained it's not necessary. The only benefit is to make it easier for you to see which value is embedded in the function (which you have to balance over the loss of actual syntax check and readability of the loop code). Matlab is happy either way.
  2 件のコメント
Leo Simon
Leo Simon 2016 年 10 月 12 日
Ugh, as usual, I over-simplified for attempted clarification. In my actual application, which is way to complicated to post, the ii wasn't replaced by an actual number, for some reason. But I'll take your response as permission to use the dreaded eval, which does work. Thanks!
Guillaume
Guillaume 2016 年 10 月 12 日
If the anonymous function fails to capture the relevant variable, then you've found a bug with matlab, so it would be interesting to know how to trigger it.
As shown, you can check what variables the anonymous function has captured with the workspace member of the return value of functions.

サインインしてコメントする。

その他の回答 (1 件)

Walter Roberson
Walter Roberson 2016 年 10 月 12 日
This cannot be done purely with recursive anonymous functions. Pure anonymous functions cannot selectively execute code, and you need a selective test to be able to return the initial value when the counter gets down to 1. You need at least one helper function that does the "if" for you.

カテゴリ

Help Center および File ExchangeMatrix Indexing についてさらに検索

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by