Is there a way to return a part of a list by reference, for reading and writing?
I want to do this so I can easily manipulate "rule-styled structured", i.e., hierarchical data that is loaded from a MAT file with struct
's. Example:
obj = {"Name" -> "Something", "Age" -> 10};
I think this is a relatively simple way to get / set fields, which deals with nested structures by limiting Position
to levelspec
1:
RuleQ[x_] := False;
RuleQ[rule_Rule] := True;
RuleQ[{}] := True; (* An empty list can be a Rule set... *)
RuleQ[rules_List] := SameQ[Head[First[rules]], Rule];
StructQ[x_] := False;
StructQ[rules_List?RuleQ] := True;
FindFirst[list_List, item_] := Module[{res},
res = Flatten[Position[list, item, 1]];
Return[If[Length[res] > 0, First[res], {}]];
];
FieldRule[field_] := field -> _;
GetFieldIndex[obj_?StructQ, field_] := FindFirst[obj, FieldRule[field]];
SetField[obj_?StructQ, field_, value_] := Module[{index},
index = GetFieldIndex[obj, field];
If[NumberQ[index],
obj[[index, 2]] = value;
,
AppendTo[obj, field -> value];
];
];
SetAttributes[SetField, HoldFirst];
GetField[obj_?StructQ, field_] := Module[{index},
index = GetFieldIndex[obj, field];
(* How to return a reference? *)
Return[obj[[index, 2]]];
];
SetAttributes[GetField, HoldFirst];
So you can do something like
Print[GetField[obj, "Name"]];
SetField[obj, "Name", "REPLACED"];
Print[GetField[obj, "Name"]];
All that being said, I would like to do something like this:
GetField[obj, "Name"] = "REPLACED";
An example of my hope for such a feature:
GetFieldByReference[obj_?StructQ, field_] :=
Return[Part[obj, {GetFieldIndex[obj, field], 2}];
SetAttributes[GetFieldByReference, HoldReturn];
obj = {"Name" -> "Something", "Age" -> 10};
GetFieldByReference[obj, "Name"] = "REPLACED";
The contents of obj
would then be:
{"Name" -> "REPLACED", "Age" -> 10}
Comments
Post a Comment