42
$\begingroup$

Which Object-Oriented Paradigm (OOP) approach to use in Mathematica for:

  • general implementation, or

  • a particular project?

There are a lot of related questions and answers in MSE on doing OOP that concentrate mostly on the "How?" but not on discussing "Why/which OOP approach?" (Or "What are the pre-conditions and consequences of using ...?")

Here is a mind-map that shows a way to compare the proposed OOP implementations and styles. (The image links to a PDF that has clickable hyperlinks.)

OOP in Mathematica approaches

It is probably best the responses of this question to be summarized in a comparison table with columns and rows derived/related to that mind-map.

Links

Here is a link to a PDF of the mind-map with clickable/linked references also given below.

Core concepts of the implementations

Objects Pure objects
  • ClasslessObjects, Jakub Kuczmarski, (2014), GitHub, MSE

  • JavaScript style

Struct object
  • MTools, Faysal Aberkane (2016), GitHub, MSE
Associations Rules
  • “The Mathematica Programmer: Object-Oriented Programming”, Maeder (1990), WLA
Classes (types)
  • Type declarations, Leonid Shifrin (2012), MSE
Object-oriented design patterns
  • “Implementation of OOP Design Patterns in Mathematica”, Antonov (2016), GitHub, WordPress

  • Uses the same approach to classes as Leonid Shifrin’s

Signature overloading Modeling interactions between classes / objects UML diagrams
  • … included since it emphasizes the necessity of big-picture view in OOP designs
  • “UML diagrams creation and generation”, Antonov, (2016), GitHub, WordPress

Comparison table (example)

\begin{array} {|r|r|} \hline \textbf{Approach} & \textbf{Core concepts} & \textbf{Properties} & \textbf{When to use?} & \textbf{Why use it?} \\ \hline ClasslessObjects \\ \hline MTools \\ \hline Class \; types \; definitions \\ \hline ... \\ \hline \end{array}

$\endgroup$
17
  • 3
    $\begingroup$ SciDraw is a very nice package for making publication quality figures. It is based on an (unpublished) OOP framework. While the framework is unpublished, the code is well commented. This project is fairly unique because it does use OOP extensively while being one of the largest and most complex freely available Mathematica packages. There are many discussions of OOP in M, but not many truly large scale applications. $\endgroup$
    – Szabolcs
    Jul 4, 2016 at 16:05
  • 2
    $\begingroup$ One problem with SciDraw is that it is quite slow. I don't know if that has anything to do with the OOP framework. It could be, but I suspect option handling to be the culprit instead. Anyway, performance should be a prime concern for any OOP framework which aims to be usable in a large project. $\endgroup$
    – Szabolcs
    Jul 4, 2016 at 16:07
  • 4
    $\begingroup$ I should say that I have another version of OOP in the works, which I have been using for my purposes for some time, and which builds on my earlier developments. This new version will arguably be much more "grown-up" version, suited for production. I should be able to publish it relatively soon. $\endgroup$ Jul 4, 2016 at 16:42
  • 5
    $\begingroup$ To the people who voted or consider voting to close the question as too broad. The question in the title is broad, but examine the mind-map. The comparison proposed there narrows down the question fairly well. The question can be answered with specific prescriptions of when and why for at least several of the approaches listed in it. $\endgroup$ Jul 5, 2016 at 10:14
  • 2
    $\begingroup$ @Eric I think there is a still good reason to have proper OOP to work with, as otherwise one will be simply adapting oop-like features with Association all the time. Fortunately as you mention OOP implementations are now pretty easy with the advent Association. $\endgroup$
    – b3m2a1
    Jul 21, 2017 at 6:21

2 Answers 2

12
$\begingroup$

Faithful OOP vs. Association

So per @AntonAntonov's suggestion I'm going to chime in on OOP vs. Association. In a comment, @Eric notes that:

"By the way, with the Association, namespace mechanism and the highy flexible rule-replacing system(contain functional programming as its small feature) in Mathematica, I roughly guess that there would be no need to think with or implement OOP anymore."

While this is partially true, I think there are a few things to consider (and note that I'm not really a programmer, so I might be spouting garbage here):

  • OOP is a paradigm, not a framework, so OOP can still be useful even if an OOP-framework is less useful that it would once have been
  • OOP and Association are fundamentally complementary

I think that last point bears some discussion, and to ground it, I'll disclose that I am biased, as most of my user-accessible code in Mathematica is object-oriented in some way. It might be code-as-data level psuedo-OOP, it might be true mutable OOP, but the paradigm is simply too useful to abandon altogether.

To start, let's consider struct-level OOP. Association makes this super easy. Just do something like:

<|
 "Username"->"b3m2a1",
 "Password"->"uh-oh-security-leak"
 |>

and you have a struct. I use this type of deal a bunch, for example here to represent notebook tabs in the TaggingRules.

To make this more useful, maybe we'll take our OOP one step further and attach some head to it, to make it a code-as-data level object:

CoolAppUser[
 <|
  "Username"->"b3m2a1",
  "Password"->"uh-oh-security-leak"
  |>
 ]

Then we can stick Format code on CoolAppUser and UpValues and junk like that. This is a powerful tool, and one of the most common ones I use.

This is most useful when you don't need to mutate your data. Generally you can get away without mutability, but sometimes it's just too useful to do without. And here's where you generally need some form of OOP framework. And here is also where we should take a detour to look at the (other) favorite language of jokes and hacks like me, python.

OOP association-wise in Python

Python is a fully-OOP language. With perhaps the exception of the most primitive of primitives, there is nothing but OOP in python. And what do python's objects look like in practice? Glorified hash-maps, which are implemented in Mathematica as associations. And if you pretty much just copy python's structure but copy it over to Mathematica, it's easy and powerful. And if you take some time to optimize, that's even better. To give a sense of just how easy, over about a year-and-a-half I've implemented 4 or so such frameworks.

Concrete implementations

The basic idea I've used is either that you make a wrapper head that holds a Symbol that can be mutated or, as I've been doing recently, making a single centralized holding symbol that tracks object and type data in a core Association and making a head that holds a pointer to an entry in that. I've found the latter to be somewhat more efficient and manageable. Note that we can do this in either a typed or untyped manner.

We need some mutability, but since we're working with a Symbol in either case we can get that out of a combo of AssociateTo and Set / SetDelayed. We can even vectorize the AssociateTo for efficiency.

And this truly is useful. It's got overhead for sure, it's relatively slow, yes, but as with everything Mathematica, if you know how to use it right, it can take you far. I use one such framework in a large chemistry package of mine, I used another version in a now-abandoned set of classes for a specific type of QM computation with random additions for databases and parallel objects and junk, and I developed one just as an exercise which I'm gonna get around to putting through its paces at some point.

Remarks

  • Just to comment on Anton Antonov's first question, I think if some OOP framework were integrated into the language it would be incredible, but I also totally understand why WRI doesn't put it in.

  • Additional comparison between Association and OOP over handling of "global" variables can be seen in this MSE answer of "Functions with changeable global variables".

Related

I made another few implementations here and here for the question How can I implement object oriented programming in Mathematica?

$\endgroup$
2
  • 1
    $\begingroup$ This is good -- thanks for answering. Some experienced Python users do say that the Object-Orientation (OO) is kind of forced in Python or bolted-in. That aligns with your explanations that OO in Python is done by glorified hash-maps. $\endgroup$ Aug 7, 2017 at 13:57
  • $\begingroup$ @AntonAntonov Thanks, the extra structure is welcome. While I would agree the Python OO isn't as strongly bound as it is in, say, Java, I do think it's an effective approach for dynamic languages such as Mathematica. $\endgroup$
    – b3m2a1
    Aug 7, 2017 at 19:09
2
$\begingroup$

I want to talk about why I specifically made my short realization and what format I chose.

Lately I have been developing small paclets that can be used for general purpose. For example a client for servers that support WebSocket protocol, a library for working with TelegramBot API or TCPServer that can be flexibly modified on the fly.

When I was working on these projects I realized that I just needed modifiable objects and I ended up creating a small package called Objects. It implements a general approach for implementing OOP It was more cumbersome at first, but gradually I removed a lot of the checks and conditions that were slowing it down.

Eventually the implementation of changeable objects just became an add-on to symbols and associations. I created mutable associations that are most like JS, but with overloading capabilities.

A typical object from my package looks like this:

obj1 = Object[]
(*Object[KirillBelov`Objects`Object`$11]*)

obj1@PropName = "property"
obj1@PropName (*"property"*)
Object[KirillBelov`Objects`Object`$11]@PropName (*"property"*)
Object[KirillBelov`Objects`Object`$11]@PropName = "new"
obj1@PropName (*"new"*)

What does this ultimately give me compared to an association? The fact that I can use type checking in a much simpler way and forget about the fact that I always have to check the form of the expression - is it a symbol or an expression that was derived from OwnValues? Now I don't think about setting Hold attributes and just work with the object and it doesn't matter if it's another reference or the object itself. In the end it just made my work in specific projects fantastically easier.

The next cool thing I apply to these objects and am happy with is inheritance. It has also made writing code in my projects a lot easier. Even the fact that I no longer need to define getters and setters for a header in every package is a plus. And the fact that I can inherit all the definitions is fantastic. For example, I've created one general kind of server for myself, and if I need to make several servers for specific purposes, I just inherit from the general one and add a small number of specific functions to it. All in all I see only one plus. I believe that choice is always better than no choice. Let WL be able to use both OOP and functional programming. Let there be immutable objects and changeable objects too. I have found a great use for both.

In the future I plan to add some new features to my project, such as multiple inheritance for example ;-) Of course if it is there and it is dangerous - you don't have to use it, but again it just gives you a choice

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.