In the (as always) insigthful answer by Leonard Shifrin to this MMA SE post
https://mathematica.stackexchange.com/questions/52393/how-to-make-use-of-associations
the makePersonInfoMutable struct implementation deals with the case where there are two struct members, corresponding to the arguments fname and lname. I wanted to extend the code to deal with the case of a variable number of struct members, with both the member names (fnames) and member data (lnames) passed as arguments. (I was actually thinking of the case where the second argument would be a list of real numbers, but the exact nature of the second argument is not relevant). The code below, mostly copied from Mr. Shifrin's answer, shows the issue:
ClearAll[makePersonInfoMutable];
makePersonInfoMutable[fname_, lname_, fnames_List, lnames_List] :=
Module[{fn = fname, ln = lname, fns = fnames, lns = lnames,
instance},
SetAttributes[instance, HoldAll];
instance[getFirstName[]] := fn;
instance[getLName[fns[1]][]] := lns[[1]];
instance@setFirstName[name_] := fn = name;
instance@getLastName[] := ln;
instance@setLastName[name_] := ln = name;
instance@getFullName[] := fn <> " " <> ln;
instance];
pinfo = makePersonInfoMutable["Leonard",
"Shifrin", {"Joe", "Mary"}, {"Smith", "Jackson"}];
pinfo@getFirstName[]
(* Leonard *)
pinfo[getLName["Joe"][]]
(* instance$1356[getName["Joe"][]] *)
I only added two lines the original code. The first one, inside the Module, is
instance[getName[fns[1]][]] := lns[[1]];
(I used 1 as the index, but more generally this could be i within a Do command, or something similar.)
The second added line of code,
pinfo[getLName["Joe"][]]
and its output show I did not get what I expected, which would be
(* Smith *)
For comparison, I placed this second added line just below the similar command in the original post, which of course works fine.
I am sure there is a way to do this, but I cannot figure it out. Any help will be greatly appreciated.s
instance[getLName[Evaluate@fns[1]][]] := lns[[1]];fix the problem?, 3) Inpinfo[getLName[fns$298[[1]]][]]I guess the execution is already outsideModule, since pinfo is already defined. If that is the case, how is fns$XXX available?, 4) If you wrap aDoaround theWith[{...}]statement, even leaving1in place instead ofithe problem reappears. Why? – Soldalma Oct 22 '16 at 00:31Do[With[{fs = fns[[i]], j = i}, instance[getLName[fs][]] := lns[[j]]], {i, n}]– Soldalma Oct 22 '16 at 00:56fns[1]tofns[[1]]. You have a typo in the code. 2) TheEvaluatewould be too deep. You would need instead (with theSetAttributeskept, otherwise it is not useful):instance[Evaluate@getLName[fns[[1]]][]] := lns[[1]]. (Note that the type is corrected here as well.) 3) The variablefns$XXXis created as soon as theModuleis called, so it can be accessed outside its scope.HoldAllattribute may not be useful in this short version of the code, so it can probably be removed. – Oct 22 '16 at 11:50