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}
SetAttribute[HoldReturn], similar to theHold...inAttributes[]. In that way, I could return a part of a list, and then assign to that knowing that it is referring directly to a subset of that list. Then that could be used to implement something likeGetField[obj, "Name"] = "REPLACED"$\endgroup$