So I've been toiling away on my DataFrame package. I've been trying to get Set to work with it, but it seems it either can't be done (ie via UpValues), or is ill advised. So I decided to bite the bullet and just roll my own custom DFSet function. But I can't figure out how the get the evaluation to work like it does when you Set the Part of something.
This is my DFSet function:
DFSet[Part[DataFrame[DFMetadata[metastore_], DFData[store_]], name_String], data_List] := ( If[ Length@data =!= metastore["Length"], Abort[] ]; If[ !MemberQ[metastore["Names"], name], metastore["Names"] = Append[metastore["Names"], name] ]; store[name] = Developer`ToPackedArray@data; ) The idea is that it would be called like this:
DFSet[frame[["a"]], {1, 2, 3}] The problem is that if I run it as is the Part bit will try to evaluate and that won't do. But if I set the attribute HoldFirst on DFSet frame won't evaluate to its OwnValue.
A test case with code:
(****Code needed for a working test case but not part of the problem****) (*Helper functions*) StringVectorQ[x_] := MatchQ[x,{__String}] TopMatrixQ[x_] := Length[Union@(Length/@x)]==1 (*Constructor*) DataFrame[names_?StringVectorQ, data_?TopMatrixQ] := Module[ {store, metastore, length}, If[Length@First@data =!= Length@names, Abort[]]; store = Unique[DFstore]; metastore = Unique[DFmetastore]; metastore["Length"] = Length@First@Transpose@data; metastore["Names"] = names; Thread[ Set[#1,#2]&[store/@names, Developer`ToPackedArray/@Transpose@data] ]; DataFrame[DFMetadata[metastore], DFData[store]] ] (*Pretty Formatting*) Format[DataFrame[DFMetadata[metastore_], _DFData]] := "DataFrame"[Length[metastore["Names"]]] (*UpValue for Part*) DataFrame /: Part[DataFrame[DFMetadata[metastore_], DFData[store_]], name_String] := ( If[!MemberQ[metastore["Names"], name], Abort[]]; store[name] ) (**************************) (****The actual problem****) (*DFSet function*) DFSet[Part[DataFrame[DFMetadata[metastore_], DFData[store_]], name_String], data_List] := ( If[ Length@data =!= metastore["Length"], Abort[] ]; If[ !MemberQ[metastore["Names"], name], metastore["Names"] = Append[metastore["Names"], name] ]; store[name] = Developer`ToPackedArray@data; ) (*******************) (****A test case****) (*Arrange*) frame = DataFrame[{"a","b"},{{1,2},{1,2},{1,2}}] (*Act*) DFSet[frame[["c"]],{3,3,3}] DFSet[frame[["b"]],{4,4,4}] (*Assert*) frame[["c"]]=={3,3,3} frame[["b"]]=={4,4,4} (****Output from successful test should be: Out=DataFrame[2] Out=True Out=True *)
frameinframe[["a"]]but notPart, within yourDFSetfunction. Is that correct? $\endgroup$