Filter löschen
Filter löschen

Updating Structure Input for Functions

5 Ansichten (letzte 30 Tage)
Jekazu
Jekazu am 8 Jan. 2024
Kommentiert: Jekazu am 9 Jan. 2024
Hello,
Let's say I have a structure for fruit:
fruit.appleMass = 0.15; %kg
fruit.appleHeight = 4; %m
Let's say I also have another structure for other variables:
otherParams.gravity = 9.81; %m/s^2
otherParams.newtonHeight = 1.68; %m
I have a simple function to calculate the force of a falling fruit and another simple function to calculate the maximum velocity of a falling fruit based on the apocryphal Isaac Newton tale:
ouch = fruitForce(fruit, otherParams);
yikes = fruitVelocity(fruit, otherParams);
function [ouch] = fruitForce(fruit, otherParams)
ouch = fruit.appleMass*otherParams.gravity;
end
function [yikes] = fruitVelocity(fruit, otherParams)
deltaHeight = fruit.appleHeight - otherParams.newtonHeight;
yikes = sqrt(2*deltaHeight*otherParams.gravity);
end
However, if later I discover I need to add another fruit to my structure, like a coconut, and need to perform the same calculations (poor Newton), I need to update the code.
Creating fields for coconuts is straightforward. Obviously, I could rewrite my functions to replace instances of apples with coconuts or add lines to calculate both apples and coconuts simultaneously. However, updating my functions each time I have a new fruit seems very ineffcient and seems highly prone to issues if I later have several function files calling fields from my fruit structure.
I think there is an easy way to update the code for an arbitrary number of fruits but not sure what that entails. What would be the best way to update and future proof the code? Should I have written the initial code differently before knowing there would be other fruits besides apples?
I have searched for similar questions and answers but didn't see anything similar (not sure what keyword I am missing). Insight would be much appreciated.
  3 Kommentare
Jekazu
Jekazu am 8 Jan. 2024
Hello Stephen,
Well, I admit I feel rather silly for missing something as simple as nonscalar structure arrays. I appreciate that you addressed many of the points in my inquiry.
Stephen23
Stephen23 am 8 Jan. 2024
Bearbeitet: Stephen23 am 9 Jan. 2024
Don't feel silly. I am just trying to show that a change of perspective helps: MATLAB is based on arrays, so you should always try to solve tasks first using arrays... and only if that does not work (unlikely) try something else.
This applies to all programming languages of course: if language X is based on Y... then it makes sense to use Y when writing code in X (at least as a starting point).
"I appreciate that you addressed many of the points in my inquiry."
Let me know what I missed, I am happy to clarify or provide examples.

Melden Sie sich an, um zu kommentieren.

Akzeptierte Antwort

Stephen23
Stephen23 am 8 Jan. 2024
Bearbeitet: Stephen23 am 9 Jan. 2024
Do not use nested structures.
Definitely do NOT use lots of variables each named after a fruit! Ugh, no.
Use a structure array:
S(1).name = 'apple'
S(1).mass = 0.15; %kg
S(1).height = 4; %m
S(2).name = 'banana'
S(2).mass = 0.1; %kg
S(2).height = 2; %m
Do not make your data any more complex than that.
Do not force meta-data (e.g. names of fruit) into fieldnames or variable names (unless you want to force yourself into writing slow, complex, inefficient, buggy code that is hard to debug). Meta-data is data: data belongs in your variables, not in the variable/field names. Data in variables makes it much easier to write expandable, generalizable, efficient code. See also Steven Lord's comment here: https://www.mathworks.com/matlabcentral/answers/2067801-updating-structure-input-for-functions#comment_3022366
Understand that meta-data is data. Then you would avoid the situation that you have gotten yourself into.
  5 Kommentare
Stephen23
Stephen23 am 9 Jan. 2024
Bearbeitet: Stephen23 am 9 Jan. 2024
"The intent of the function name question was to ask whether or not function names should be as generic as possible or as specific as desired (including metadata like "fruit" in the name). I think for the falling fruit problem, a very generic function name could be "fallingObjectForce" compared to "fruitForce"."
Ah, I see. That is actually a good question. Personally, I would keep functions (and their names) as general as is reasonable**: it often happens that once you do that, other ways to use your functions or approaches to processing your data will appear.
But for a start just focus on robust data design and efficient code.
** You will note that this just shifts the question to "what is reasonable?" Like all other types of engineering, writing code is ultimately a matter of compromise between many many many factors (e.g. correctness, readability, understandability, debuggability, complexity, expandability, generalizability, runtime, maintenance time, etc.) How to balance those priorities depends on you, your projects, your experience, your goals, etc.
If my answer helped you to resolve your original question then please remember to click the accept button!
Jekazu
Jekazu am 9 Jan. 2024
Hello Stephen,
I accepted your answer. Thanks for your patience and all of the assistance.

Melden Sie sich an, um zu kommentieren.

Weitere Antworten (2)

Matt J
Matt J am 8 Jan. 2024
Bearbeitet: Matt J am 8 Jan. 2024
If you had as follows, it would work for any fruit, wouldn't it?
fruit.Mass = 0.15; %kg
fruit.Height = 4; %m
  6 Kommentare
Matt J
Matt J am 8 Jan. 2024
If the name of the fruit is meta-data...
Stephen23
Stephen23 am 8 Jan. 2024
"If the name of the fruit is meta-data..."
It is.

Melden Sie sich an, um zu kommentieren.


Walter Roberson
Walter Roberson am 8 Jan. 2024
Verschoben: Walter Roberson am 8 Jan. 2024
What if you did something like
fruit.apple.Mass = 0.15; %kg
fruit.apple.Height = 4; %m
fruit.coconut.Mass = 0.89; %kg
fruit.coconut.Height = 4; %m
then you could use dynamic field name references:
fn = fieldnames(fruit);
for fi = 1 : length(fn)
thisfruit = fn{fi};
deltaHeight = fruit.(thisfruit).Height - otherParams.newtonHeight;
yikes.(thisfruit) = sqrt(2*deltaHeight*otherParams.gravity);
end
and the output would be a struct array with one field for each fruit.
  1 Kommentar
Jekazu
Jekazu am 8 Jan. 2024
Hello Walter,
That gives the desired information into a desired format for me. Nested structures seems intuitive, but I hadn't thought about using a cell in a "for" loop before. I really appreciate the response.

Melden Sie sich an, um zu kommentieren.

Kategorien

Mehr zu Matrix Indexing finden Sie in Help Center und File Exchange

Produkte


Version

R2023b

Community Treasure Hunt

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

Start Hunting!

Translated by