On 03/09/2021 13:27, James Harris wrote:
> On 30/08/2021 22:13, Dmitry A. Kazakov wrote:
>> On 2021-08-30 22:25, James Harris wrote:
>>> On 30/08/2021 12:36, Dmitry A. Kazakov wrote:
>
> ...
>
>>>> In the most general case a dispatching table belongs to the method,
>>>> not to the type. The tag would denote an N-th coordinate (plane) of
>>>> the multidimensional index in the table.
>>>
>>> That sounds weird. If the dispatch table belongs to the method what
>>> would it be indexed by?
>>
>> By the type, of course. It is pretty straightforward. Consider
>>
>> Surface Shape
>> / \ / \
>> PDF SVG Ellipse Rectangle
>>
>> Draw | PDF | SVG |
>> ----------+-----+-----+
>> Ellipse | ptr | ptr |
>> ----------+-----+-----+
>> Rectangle | ptr | ptr |
>> ----------+-----+-----+
>
> That solution looks as though the shapes would have to know how to draw
> themselves on different surfaces. As such I doubt it would scale well as
> new shapes and new types of surface were added. But maybe it's purely
> illustrative of multiple dispatch.
(The example reminds me of actual drawing code I needed to write in my
applications in the 1990s. The script language included functions such
as a general-purpose one called Plot(), with 8 parameters (many optional
with defaults). The remaining docs are poor but I think they were:
Dest Destination code
D Info specific to a destination
Scan Scan type
View View point
P Drawing element
Clear Whether to clear destination first
Nsegments 1, or build results as multiple hoz bands
Flags Misc
This is for displaying a 3D model, which is represented in P as a
hierarchical tree of drawing elements. There were nearly 50 leaf objects
(including Rectangle and Ellipse!) plus named collections which in a HLL
would correspond to a named function call.
Dest is a code broadly indicating one of Window, Image, Printer/Plotter,
or collections of 3D Face or Lines. Here D might refer to the actual
window, a filename to capture output (eg. EPS print format) etc.
Scan indicates how the data should be processed, with 16 variations,
including Wireframe, Hidden, Shaded, Erase, Highlight, DXF dest, Expand
to lines/faces, ...
View specifies the viewpoint from which the result will be rendered, and
whether it uses perspective projection.
Flags controls many other factors: whether to draw grids or axes, page
outlines ...
OK, the example was clearly a simple one to illustrate some aspects of
how OOP works. But I see such examples using shapes all the time and
find them somewhat annoying.
It gives the impression that OOP can magically solve all the problems
that come up in actual applications, but the reality is always a lot
more complicated.
I'm rather sceptical about what OOP can do, and I have firm views on how
far a language should get involved in matters that should be the concern
of an application.
I also think that, if you really want to use OOP seriously, then you're
quite liable to just end up reinventing C++, as you meet the same
obstacles.)
What I take from it is that, however
> it's done, the address of the drawing function (the ptr in the above
> table) would need to be found from a key of three parameters
>
> (shape type, surface type, function name)
>
> whereas single dispatch would find a function based on two parameters
> such as
>
> (shape type, function name)
>
> Is that correct?
The shape should describe the shape itself and nothing else. If you want
to plot it, then extra information is needed:
p.plot(surface_type)
With perhaps that parameter being optional when there is a sensible
default. So here there is single dispatch based on shape type.
Anything else would be difficult to get your head around. If there are M
shape types and N surface types, then you've got MxN methods to write,
but where are you going to write them? Functions are written one after
the other, not in a table!
You might consider introducing overloaded functions, so the plot()
method for Rectangle is split into one each for PDF and SVG. Feature creep.
(My approach as I used was single dispatch - a simple switch - using
common code to reduce complex objects to basic edges, and then using
single dispatch on the 'surface' when drawing those edges.)