A workaround to use "." to access class member functions - is it unJulian?

108 views
Skip to first unread message

Zhong Pan

unread,
Jul 22, 2016, 1:01:42 PM7/22/16
to julia-users
Most people coming from the object-oriented programming (OOP) world are used to using "." to access member methods/functions of a class. Consider the following simple example in Python that defines a class AA which has two members: an integer variable N to store the number of people attended, and a split(cost) function to calculate the cost split evenly among all attendees.
class AA:
    def __init__(self, n):
        self.N = n

    def split(self, cost):
        return float(cost) / self.N

groupdinner = AA(20)
totalcost = 500.00
print("{:d} people attended the group dinner, and each should pay ${:.2f}".format(groupdinner.N,
                                                                                  groupdinner.split(totalcost)))

Running the above code gives:
20 people attended the group dinner, and each should pay $25.00

In Julia, with multiple dispatch and functions as first-class objects, the code would usually be written this way:
type AA
  N :: Int
end

split(event::AA, x::Number) = x/event.N

groupdinner = AA(20)
totalcost = 500.00
@printf("%d people attended the group dinner, and each should pay \$%.2f\n", groupdinner.N, split(groupdinner, totalcost))

However, if someone insists that a class (or type in Julia) should "own" the member functions, I do see a workaround using inner constructor, like this:
type AA
  N :: Int
  split :: Function

  AA(n::Int) = new(n, (x::Number) -> x/n)
end

groupdinner = AA(20)
totalcost = 500.00
@printf("%d people attended the group dinner, and each should pay \$%.2f\n", groupdinner.N, groupdinner.split(totalcost))

This approach treats member functions as Function objects owned by a type, and the implementations of member functions are actually written in an inner constructor. 

Obviously this is a workaround and workarounds are awkward. However, I do see one potential practical use: modern IDEs often provide intellisense which will display an object's members once "." is typed after an object name. It's quite handy when I want to use a mature 3rd party module that I don't have time to learn by reading documentation; instead I just want to quickly try and use it by exploring the class hierarchy. It also saves a lot of memorizing/typing when I can be constantly reminded/auto-completed of matching variable/function names filtered by the object before the "." and the first few letters I typed in after the ".".

In Julia one can use methods(AA) to display all functions that take AA object(s) as input(s). However, the list produced is often quite long and hard to read, since multiple dispatch will create many versions of the same function, with each differing only in the parameter types, and "methods" will show all of them with parameter types but no meaningful names. Also not sure how intellisense can help here. So the only way to explore for now is to know the function name (or at least a significant leading part of the name) and read its documentation by using "?" in a terminal, separate from the source code editor. 

With the "." workaround shown above intellisense should be able to prompt the name "split" alongside with "N".

I just wonder if this workaround would be considered way too "unJulian" that it ought to be denounced. :-)

Thanks,
-Zhong












Jeffrey Sarnoff

unread,
Jul 22, 2016, 1:19:46 PM7/22/16
to julia-users
Too much riffle-raffle for the gain you mention (imo).

Tom Breloff

unread,
Jul 22, 2016, 1:51:43 PM7/22/16
to julia-users
In julia 0.4, I think this would be considered both slow and ugly.  Since the improvements to anonymous functions in 0.5, it's now only ugly.  :)

I think you'll find a lot of benefit if you forget about OO-programming, and use multiple dispatch.  "You must unlearn what you have learned!"

Zhong Pan

unread,
Jul 22, 2016, 2:28:09 PM7/22/16
to julia-users
OK, I admit, it's ugly. :-) 

Now I realize it's also wrong. In the example, the inner-constructor-created member function split() cannot see member variable "N"; it can only see parameter "n" that is passed in from outside. If the code changes N later on, the split() function will be using a stale value. 


Jeffrey Sarnoff

unread,
Jul 22, 2016, 2:38:11 PM7/22/16
to julia-users
(big step ..!)
Reply all
Reply to author
Forward
0 new messages