# Create user-defined structured data type in WL?

Posted 1 month ago
439 Views
|
9 Replies
|
3 Total Likes
|
 I cannot find some sort of user defined structured data type like Record or Type in other languages. I always use nested list or associations instead of that, which is not really comfortabel. Is it true that I cannot define my data types at will?As an example in, say, VBA I would write something like: ' --- User-defined Types Type T_POINT x As Double y As Double End Type Type T_STATE p As T_POINT s As Double End Type ' --- User-defined data Dim myState As T_STATE ' --- Use such data types Sub CB_init_Click() init myState With myState Range("s_px") = .p.x Range("s_py") = .p.y Range("s_s") = .s End With End Sub Sub init(state As T_STATE) With state .p.x = 1 .p.y = 2 .s = Rnd() End With End Sub In WL I would have to use lists, something like: p = {1, 2}; state = {p, RandomReal[]}; Print["state: \t", state]; Print["state.p: \t", state[[1]], "\tstate.p.y: ", state[[1, 2]]]; Print["state.s: \t", state[[2]]]; state: {{1,2},0.851364} state.p: {1,2} state.p.y: 2 state.s: 0.851364 Or associations, something like: p = <|"x" -> 1, "y" -> 2|>; state = <|"p" -> p, "s" -> RandomReal[]|>; Print["state: \t", state]; Print["state.p: \t", state["p"], "\tstate.p.y: ", state["p"]["y"]]; Print["state.s: \t", state["s"]]; state: <|p-><|x->1,y->2|>,s->0.198831|> state.p: <|x->1,y->2|> state.p.y: 2 state.s: 0.198831 Both are certainly fast, but not very readable (in particular the list-form). And I cannot really force a variable assignment to a certain data type, i.e. a pattern. For example in the association-case I could define named patterns like: Pattern[TPOINT, <|"x" -> _Number, "y" -> _Number|>]; Pattern[TSTATE, <|"p" -> _TPOINT, "s" -> _Number|>]; But how can I then force the assignments above to p and state to obey those patterns? Favourably at compiletime, not runtime?
9 Replies
Sort By:
Posted 1 month ago
 You are referring to object-oriented programming, which does not really exist in Mathematica. If you look for it online you will find some people who emulated it:https://mathematica.stackexchange.com/questions/6497/how-can-i-implement-object-oriented-programming-in-mathematicahttps://mathematica.stackexchange.com/questions/52393/how-to-make-use-of-associations/54493#54493https://mathematica.stackexchange.com/questions/tagged/object-oriented?sort=votes&pageSize=50
Posted 1 month ago
 Mathematica is a language for recognizing expressions by structure and rewriting them according to rules. This is very different from the sort of procedural languages you are familiar with. Something like: a["state"] = 4 simply means "when you see a["state"], replace it with 4". You're not really "indexing" anything.
Posted 1 month ago
 Hello Werner,if I understood your post correctly, it contains basically two questions:(1) how to make an expression in Mathematica type safe, so that incorrect types raise an error message(2) how to create structures data typesMathematica works more like an interpreter than a compiler, but supports compilation of functions. This can be employed to raise error messages in case of a type missmatch (which you already mentioned). Below is code (requires M12) that shows this for your examples: Needs["Experimental"] First we define a function with excepts typed data, namely a list of two Real64. tPointF = Function[ Typed[list1, TypeSpecifier["PackedArray"]["Real64", 1]], list1] Next the function is compiled: tPointT = FunctionCompile[tPointF] Now we instantiate this function with two arguments, the first one fits the spec, whereas the second arguments is a list of two integers: {tPointT[{1.23, 4.56}], tPointT[{1, 4}]} The same can be done for a function that accepts one Real64: zahlF = Function[Typed[zahl, "Real64"], zahl]; zahlT = FunctionCompile[zahlF]; Next step is to build a structure like datatype. The closest I came up with is a dataset: createDataInstance[list_, zahl_] := Dataset[<|"p" -> tPointT[list], "z" -> zahlT[zahl]|>] myDataInstance = createDataInstance[{1., 2.}, RandomReal[]] Using a dataset you can access the data similar like from a struct: {myDataInstance, myDataInstance["p"], myDataInstance["z"]} And you can extract the raw data from it using Normal: {myDataInstance // Normal, myDataInstance["p"] // Normal, myDataInstance["z"]} Is this what you had in mind?
Posted 1 month ago
 No, I do not refer to OOP, but much less. Just user-defined data types as they are in common in practically every classic programming language for about 50 years (Algol, Pascal, C, PL/1, Cobol, VB, Matlab, etc.).Of course, I know about OOP (C++, Java, Smalltalk, etc.) and even how it can be more or less emulated in every 3rd-generation programming language. But this is not what I want to do with Wolfram Language.I think associations, as described above, are the best approximations in WL. What is missing is compile-time checking of the data.
Posted 1 month ago
 I mean you can just do this: a["state"] = 4 a["test"] = 3 and then you can just query those: If[a["state"]==4, Print["woohoo!"]] where a is just a symbol.But you can do the same with a being an Association.
Posted 1 month ago
 Hmm, this is strange. I did not know that I can index any symbol by a string. Very similar to associations. But less useful. My example would now read: p["x"] = 1; p["y"] = 2; state["p"] = p; state["s"] = RandomReal[]; Print["state: \t", state]; Print["state.p: \t", state["p"], "\tstate.p.y: ", state["p"]["y"]]; Print["state.s: \t", state["s"]]; state: state state.p: p state.p.y: 2 state.s: 0.428189 `Note that for example state["p"] gives the expected value {1,2} if state and p are associations. But it just gives the name p in the case of symbols.Anyway. For the moment I go ahead with associations.
Posted 1 month ago
 Ja, thanks for the explanation. This is clear now.