Skip to main content

programming - How does thing["property"] syntax work?


Many builtin "things" support the (usually undocumented) syntax thing["property"], and usually the available properties can be listed using thing["Properties"] (thing["Methods"] might work too).


Examples include InterpolatingFunction, FittedModel, DateObject, a lot of mesh region stuff and FEM stuff.


These symbols act essentially like objects, used only as arguments to other functions that access their properties (e.g. PredictorFunction), or whose properties are accessible with DownValue syntax (e.g. ClassifierMeasurements).


Moreover, these functions, like PredictorFunction[] are returned with this frequently encountered DisplayForm:


enter image description here



These "object-like" symbols are typically (nested) Associations wrapped in their symbol, the FullForm of the PredictorFunction above is:


PredictorFunction[Association[Rule["Basic",Association[Rule["ExampleNumber",4],Rule["FeatureNumber",1],Rule["ScalarFeature",True]]],Rule["CommonFeaturePreprocessor",MachineLearning`PackageScope`Preprocessor["InputMissing",List[List[4]]]],Rule["PredictionPreprocessor",MachineLearning`PackageScope`Preprocessor["Standardize",List[5.25`,2.7233557730613653`]]],Rule["ProbabilityPostprocessor",Identity],Rule["Combiner",MachineLearning`PackageScope`Combiner["First"]],Rule["Decision",Association[Rule["Prior",Automatic],Rule["Utility",Function[DiracDelta[Plus[Slot[2],Times[-1,Slot[1]]]]]],Rule["Threshold",0],Rule["PerformanceGoal",Automatic]]],Rule["Models",List[Association[Rule["Method","LinearRegression"],Rule["Theta",List[List[0.`],List[0.9954921542867711`]]],Rule["DistributionData",List[NormalDistribution,List[0.11611695002854867`]]],Rule["L1Regularization",0],Rule["L2Regularization",0.00001`],Rule["ExtractedFeatureNumber",1],Rule["FeatureIndices",List[1]],Rule["FeaturePreprocessor",MachineLearning`PackageScope`Preprocessor["Sequence",List[MachineLearning`PackageScope`Preprocessor["Standardize",List[List[4.`],List[Times[2,Power[Rational[5,3],Rational[1,2]]]]]],MachineLearning`PackageScope`Preprocessor["PrependOne"]]]]]]],Rule["FeatureInformation",List[Association[Rule["Name","feature1"],Rule["Type","Numerical"],Rule["Sparsity",0.`],Rule["Quantiles",List[1,1,1,3,3,5,5,7,7]]]]],Rule["PredictionInformation",Association[Rule["Quantiles",List[2.`,2.`,2.`,4.5`,4.5`,6.`,6.`,8.5`,8.5`]],Rule["Name","value"],Rule["Sparsity",0.`]]],Rule["Options",List[Rule[Method,List[Rule[List[1],List["LinearRegression",Rule["L1Regularization",0],Rule["L2Regularization",0.00001`]]]]]]],Rule["Log",Association[Rule["TrainingTime",0.039456`],Rule["MaxTrainingMemory",186792],Rule["DataMemory",424],Rule["FunctionMemory",8936],Rule["LanguageVersion",List[10.1`,0]],Rule["Date","Tue 11 Aug 2015 18:32:58"],Rule["ProcessorCount",4],Rule["ProcessorType","x86-64"],Rule["OperatingSystem","MacOSX"],Rule["SystemWordLength",64],Rule["Events",List[Association[Rule["Event","ParseData"],Rule["StartTime",0.000109`2.1879414957726175],Rule["ElapsedTime",0.000446`],Rule["MaxMemoryUsed",15176],Rule["StartMemory",3096],Rule["EndMemory",4144]],Association[Rule["Event","TrainModel"],Rule["StartTime",0.001426`3.3046345233478402],Rule["ElapsedTime",0.037726`],Rule["MaxMemoryUsed",164080],Rule["StartMemory",9096],Rule["EndMemory",13824]]]]]]]]

How can I recreate this sort of functionality with my own objects and functions? Are there any methodologies for writing down-values of symbols like this?


Example:


Here's a mini demo of what I'm talking about:


c = note[<|"Pitch"->pitch[0],"Duration"->1|>];
e = note[<|"Pitch"->pitch[4],"Duration"->1|>];
g = note[<|"Pitch"->pitch[7],"Duration"->1|>];
cc = chord[<|"Notes"->{c,e,g}|>];


I'd have to do something ugly like this:


In[2]:= c_chord[property_String] := (c[[1]])[property]

To get this to work:


In[3]:= cc["Notes"]
Out[3]= {note[<|"Pitch" -> pitch[0], "Duration" -> 1|>],
note[<|"Pitch" -> pitch[4], "Duration" -> 1|>],
note[<|"Pitch" -> pitch[7], "Duration" -> 1|>]}

Answer





How can I recreate this sort of functionality with my own objects and functions? Are there any methodologies for writing down-values of symbols like this?



If you want to know how to get a similar output format, here's a silly toy example:


(* The icon isn't really that important *)
icon = Plot[Sin[x], {x, -5, 5}, Axes -> False, Frame -> True,
ImageSize -> Dynamic[{Automatic, 3.5 (CurrentValue["FontCapHeight"] / AbsoluteCurrentValue[Magnification])}],
GridLines -> None, FrameTicks -> None, AspectRatio -> 1,
FrameStyle -> Directive[Opacity[0.5], Thickness[Tiny], RGBColor[0.368, 0.507, 0.71]]];


(* SummaryItemAnnotation and SummaryItem are the styles used in the labels *)
label[lbl_, v_] := Row[{Style[lbl <> ": ", "SummaryItemAnnotation"], Style[ToString[v], "SummaryItem"]}];

(* Set up formatting *)
BigStupidFunction /: MakeBoxes[ifun : BigStupidFunction[s1_, s2_, hs1_, hs2_], fmt_] :=
BoxForm`ArrangeSummaryBox[
BigStupidFunction, ifun, icon,
{label["Some stuff", s1], label["Other stuff", s2]},
{label["Hidden stuff 1", hs1], label["Hidden stuff 2", hs2]},
fmt

];

Now the output format of BigStupidFunction will be nicely boxed up like InterpolatingFunction.


enter image description here


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

How to thread a list

I have data in format data = {{a1, a2}, {b1, b2}, {c1, c2}, {d1, d2}} Tableform: I want to thread it to : tdata = {{{a1, b1}, {a2, b2}}, {{a1, c1}, {a2, c2}}, {{a1, d1}, {a2, d2}}} Tableform: And I would like to do better then pseudofunction[n_] := Transpose[{data2[[1]], data2[[n]]}]; SetAttributes[pseudofunction, Listable]; Range[2, 4] // pseudofunction Here is my benchmark data, where data3 is normal sample of real data. data3 = Drop[ExcelWorkBook[[Column1 ;; Column4]], None, 1]; data2 = {a #, b #, c #, d #} & /@ Range[1, 10^5]; data = RandomReal[{0, 1}, {10^6, 4}]; Here is my benchmark code kptnw[list_] := Transpose[{Table[First@#, {Length@# - 1}], Rest@#}, {3, 1, 2}] &@list kptnw2[list_] := Transpose[{ConstantArray[First@#, Length@# - 1], Rest@#}, {3, 1, 2}] &@list OleksandrR[list_] := Flatten[Outer[List, List@First[list], Rest[list], 1], {{2}, {1, 4}}] paradox2[list_] := Partition[Riffle[list[[1]], #], 2] & /@ Drop[list, 1] RM[list_] := FoldList[Transpose[{First@li...

front end - keyboard shortcut to invoke Insert new matrix

I frequently need to type in some matrices, and the menu command Insert > Table/Matrix > New... allows matrices with lines drawn between columns and rows, which is very helpful. I would like to make a keyboard shortcut for it, but cannot find the relevant frontend token command (4209405) for it. Since the FullForm[] and InputForm[] of matrices with lines drawn between rows and columns is the same as those without lines, it's hard to do this via 3rd party system-wide text expanders (e.g. autohotkey or atext on mac). How does one assign a keyboard shortcut for the menu item Insert > Table/Matrix > New... , preferably using only mathematica? Thanks! Answer In the MenuSetup.tr (for linux located in the $InstallationDirectory/SystemFiles/FrontEnd/TextResources/X/ directory), I changed the line MenuItem["&New...", "CreateGridBoxDialog"] to read MenuItem["&New...", "CreateGridBoxDialog", MenuKey["m", Modifiers-...