Hi friends!
After spending an hour on a seemingly simple problem I was not able to figour out what is wrong and this is why
I am bothering you, Consider the following commands:
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=vectorize(f);f=str2func(f);f(1)
which gives me an error saying that "Unrecognized function or variable 'D0'.". But, when I copy the second line and run it, it works!!! To get what I mean the following is what happend on my command window exactly (see also a printscreen of my command window attached)
>> D0=1;D1=1;
f=@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)];
f=vectorize(f);
f=str2func(f);
f(1)
Unrecognized function or variable 'D0'.
Error in code2>@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
>> f=@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)];
>> f(1)
ans =
-1.5
1
I find this really crazy and am impatiently looking forward to hear from you.
Thanks in advance!
Babak

댓글 수: 4

Stephen23
Stephen23 2022년 1월 14일
"A very strange problem"
It is not a strange problem at all.
The STR2FUNC documentation clearly states in the second sentence of its description that "Function handles created using str2func do not have access to variables outside of their local workspace or to nested functions" and warns that an error will be thrown if you try to access such variables.
Reading the documentation is the best way to know what a function does.
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 14일
OK. I did not know this.
But, the question is : "why matlab is like this?". It makes it so difficult to write a code.
Anyway, do you have a solution to this. Because I did not expect this I have spent some weeks and prepared extremely long function handles which are saved as text files. Now, I need to remove ' ' around them.
Any idea?
Stephen23
Stephen23 2022년 1월 14일
편집: Stephen23 2022년 1월 14일
"why matlab is like this?"
In a word: scoping.
Computers cannot read your mind (yet), they have to follow rules. Those rules include where variables/functions/whatever are visible (scoping) to other functions or operators. Although in theory a computer could look in every existing workspace for a variable, there are several major problems with this approach:
  • workspaces change, meaning that different variables come in and out of scope, leading to unpredictable code which is almost impossible to debug.
  • it would be slooooooooooow.
"I have spent some weeks and prepared extremely long function handles which are saved as text files."
Function handles store information about their scope when they are created: you can save function handles in .mat files. Converting to text or storing functions as text does not store any of this information, so your design is fundamentally lossy.
Steven Lord
Steven Lord 2022년 1월 14일
If your functions are that long, change your text files to MATLAB function files and use function handles to those files. This could also allow you to extract out common code segments into helper functions that can be called by one or more of your large function files.

댓글을 달려면 로그인하십시오.

 채택된 답변

John D'Errico
John D'Errico 2022년 1월 14일
편집: John D'Errico 2022년 1월 14일

0 개 추천

I suppose this is a subtle problem that bears explanation.
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
That does NOT create a function handle named f. It is a string. Next, you do this:
f=vectorize(f)
f = '@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]'
That just produces a new string. Still not a function.
f=str2func(f)
f = function_handle with value:
@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
So finally, f exists as a function handle. WHEW!
f(1)
Unrecognized function or variable 'D0'.

Error in solution>@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
But what happened? str2func creates a function handle, returning a result. But str2func does not have D0 in its workspace. So when you try to use f, in the form of f(1), things fail. f does not know the value of D0 or D1, because they do not exist in the workspace of the function str2func.
However, if I do this:
f= @(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f =
function_handle with value:
@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f(1)
ans =
-1.5
1
now f works, because D0 and D1 were available to f when I created that function handle. It encapsulates them in the workspace internal to the function handle, and all is good. However, f is not "vectorized", as a function of the variable dt.
Anyway, a problem exists, because f returns a vector. you would need to carefully define what that result will be when dt is itself a vector or an array. And as importantly, suppose dt was a row vector, versus a column vector? That code for f, if you blindly throw the vectorize function at it, will produce some screwy results. Magical functions like vectorize are not that intelligent.
Instead, it is far better to vectorize the code yourself. So I might do this, in a way that is insensitive to the shape of dt as a row or column vector.
fvect = @(dt)[(-D0)*dt(:).^0.5+(-D0*D1)*dt(:).^1.5/2 , 1/2*(-1+(1)+(2*D1+2*D0^2)*dt(:)/2)].'
fvect(1)
ans =
-1.5
1
fvect(1:5)
ans =
-1.5 -2.8284 -4.3301 -6 -7.8262
1 2 3 4 5
fvect((1:5)')
ans =
-1.5 -2.8284 -4.3301 -6 -7.8262
1 2 3 4 5
So fvect has been carefully vectorized to produce a result that is consistent with f when called with scalar input, but when called with a vector input, it produces a 2xn array.
Finally, because fvect was constructed directly, it fully encapsulates the values of D0 and D1 as they were found in the workspace when fvect was created.
But expecting vectorize to successfully do that is a bit too much, certainly to know the values of D0 and D1.

댓글 수: 5

Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 14일
Thanks for your respnse. But, your following answer
f= @(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f =
function_handle with value:
@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
f(1)
ans =
-1.5
1
does not fixes my problem. Why? Because I need to run it thousands of times inside a code. If I let f to be displayed then this badly reduces the speed.
Torsten
Torsten 2022년 1월 14일
편집: Torsten 2022년 1월 14일
Then place a semicolon behind the line
f = @(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 14일
Doesn't if affect the speed? I think it still affects the speed because my expressions are extremely long (here, I just showed you a tiny expression).
John D'Errico
John D'Errico 2022년 1월 14일
편집: John D'Errico 2022년 1월 14일
Yes it does fix your problem, as long as you put a semi-colon on the line! I left off the semi-colon at the end of the line just so you could see the result is indeed a function handle.
When you add a semi-colon to the end of the line, it prevents the display from going to the command window. This will now be fast, since the time spent lies in MATLAB formatting the results for display, in scrolling the command window, etc.
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 14일
Thanks Torsten for your precious time!

댓글을 달려면 로그인하십시오.

추가 답변 (2개)

KSSV
KSSV 2022년 1월 14일

1 개 추천

f='@(D0,D1,dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=vectorize(f);
f=str2func(f);
D0=1;D1=1;dt=1 ;
f(D0,D1,dt) % you need to input three variables to the function
ans = 2×1
-1.5000 1.0000

댓글 수: 3

Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 14일
Thanks for your answer. But, there is a reason I do not want to define f based on 3 inputs (because the last two inputs are sort of parameters not variables)
Matt J
Matt J 2022년 1월 14일
편집: Matt J 2022년 1월 14일
Yes, but that can be achieved with a very small modification.
f='@(D0,D1,dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=vectorize(f);
f=str2func(f);
D0=1;D1=1;;
f=@(dt)f(D0,D1,dt);
f(1)
ans = 2×1
-1.5000 1.0000
Mohammad Shojaei Arani
Mohammad Shojaei Arani 2022년 1월 15일
This is a clever and beautiful solution! (I wish if matlab could use AI techniques and tell me "did you want this?" so that I would not waste a lot of time for such things)
Trying to understand why your therapy works. Perhaps, the clue is that in your solution D0 and D1 are defined after the command f=str2func(f) while in my case if was before.

댓글을 달려면 로그인하십시오.

Matt J
Matt J 2022년 1월 14일

1 개 추천

An alternative solution is to download afslim() from,
D0=1;D1=1;
f='@(dt)[(-D0)*dt^0.5+(-D0*D1)*dt^1.5/2;1/2*(-1+(1)+(2*D1+2*D0^2)*dt/2)]';
f=afslim(vectorize(f),D0,D1)
f = function_handle with value:
@(dt)[(-D0).*dt.^0.5+(-D0.*D1).*dt.^1.5./2;1./2.*(-1+(1)+(2.*D1+2.*D0.^2).*dt./2)]
f(1)
ans = 2×1
-1.5000 1.0000

카테고리

도움말 센터File Exchange에서 Entering Commands에 대해 자세히 알아보기

Community Treasure Hunt

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

Start Hunting!

Translated by