[Gambas-user] Interpreter's treatment of classes

Bruno Félix Rezende Ribeiro oitofelix at ...181...
Fri Apr 11 05:17:40 CEST 2014


Hello Gambas users and developers!

I've been studying Gambas for almost a week and a half and I'm very
impressed with the simplicity and elegance of Gambas' object oriented
Basic language implementation.  Congratulations to all developers,
specially Benoît Minisini.  What a superb software development
environment you've shared with us!  I hope I can join you soon to work
on its development.

In the mean time, I'd like to kindly ask for some clarifications
regarding the treatment of classes by the interpreter.

Let 'MMain' be the main module of a Gambas program and the
meta-syntactic variables 'CLASS-CLASS' and 'OBJECT-CLASS' be the
expressions 'MMain' and 'Class.Load("MMain")' respectivelly. Consider
the evaluation of the following expressions inside the 'Main' method of
'MMain' module:

  TypeOf(CLASS-CLASS) ==> gb.Class
  TypeOf(OBJECT-CLASS) ==> gb.Object

As you can see the CLASS-CLASS expression yields a class, while
OBJECT-CLASS expression yields an object.  One might wonder what's the
class of the latter: 

  OBJECT-CLASS Is Class ==> True

That's expected as we may presume OBJECT-CLASS evaluates to an object,
of the class 'Class', which describes the class 'MMain', which in its
turn is the result of the evaluation of CLASS-CLASS.  Surprisingly
enough, when one applies the same expression to CLASS-CLASS they
obtain:

  CLASS-CLASS Is Class ==> True

The only possible explanation is that CLASS-CLASS is simultaneously a
class and an object.  However, it doesn't behave as an usual instance of
the class 'Class'.  For instance, it is impossible to access the public
methods and properties defined within the class 'Class' using some
expression like 'CLASS-CLASS.SYMBOL' where the meta-syntactic variable
'SYMBOL' is a public symbol of the class 'Class'.  Therefore, the
assertion that CLASS-CLASS evaluates to some object which is an
instance of the class 'Class' is somewhat meaningless underneath the
usual concept of class/instance of object oriented programming.

My first question is: why does Gambas behave this way?  What's the
reasoning backing up the exception to the general rule that the
evaluation of 'CLASS-CLASS', while an instance of the class 'Class',
represents? Would not it be simpler and more intuitive (hopefully
without loss of technical merits) to take CLASS-CLASS as just a "pure"
class?

I came to this issue while writing a method for validation of function
signatures in a component I'm working on.  It works well with methods
residing in dynamic classes, since given an object 'OBJECT' which is an
instance of a dynamic class 'CLASS' which implements the method
'METHOD', one can easily obtain the method's signature with the
expression 'Object.Class(OBJECT)["METHOD"].Signature'.  However, for
static classes I couldn't find a way to obtain the signature directly
from the class object given that
'Object.Class(CLASS)["METHOD"].Signature' wouldn't work since
'Object.Class(CLASS)' evaluates to the class 'Class' and not 'CLASS' as
would be desired, and we couldn't use it directly as in the expression
'CLASS["METHOD"].Signature' as one would naturally expect after
pondering about the fact, pointed out above, that 'CLASS Is Class'
yields 'True'.

The only way I have succeeded to obtain the signature is using the name
'NAME' of the static class 'CLASS' within the expression
'Class.Load("NAME")["METHOD"].Signature'.  That is unfortunate because
I'm compelled to discriminate between static and dynamic classes, not
to mention I need to find a way to obtain the name of a static class
from itself.  I thought there could be a more elegant solution. Is
there?  The ideal solution would be to provide a general way to get the
"true" object of the class 'Class' which describes the class 'CLASS',
since the fact that 'CLASS' is a "false" (and bastard) object of the
class 'Class', and therefore doesn't describe its own properties while
a Class --- but the properties of its objects --- is immaterial to any
practical application I could think of.  Summarizing: currently it
seems only to be possible to obtain an object of the class 'Class'
which describes the class 'CLASS' if you have an object which is an
instance of it; therefore it only works for dynamic classes, and you
have the burden of instantiation.  Maybe I haven't looked into the
right place.  Could you, please, help me?

Related to this issue is the problem of having a variable callback
function as a property of some object from a given class.  What do you
think is the best way to setup a callback function for a method? Just
to make it less abstract: I'm writing a component for plotting
arbitrary numeric functions.  The class 'Plot' implements all the plot
logic, but it must callback a function, defined by the parent which
instantiates it, to calculate the plot points.  What's the best way to
implement this behavior?  I've tried defining an event for 'Plot' class
so each time the 'Plot' object would need to (re)calculate the points,
let's say for a change in the intended interval of the function's
domain, the event would be raised, so the parent would have to be
observing the 'Plot' object to intercept the raised event and then do
the calculation.  The problem is that by design the event handlers
don't return values to the offending object, so the event handler at
hand would have to make sure of returning it in some other
pre-established manner, like storing the computed point in 'Last.Y', and
there would be no check from the interpreter about the implementation
following the function's signature and returning a 'Float' value, for
example.  So, I decided instead to store the object and method's name
that implements the mathematical function into the Plot object, so it
could call it for the computation of points and invariably receive a
return value.  But for that to work correctly I needed to check the
function's signature. That's why I ultimately came to the issues
presented above.  One initial hope I had was that 'Function' were a
native type of Gambas, as suggested by the expression evaluation
'TypeOf(FUNCTION) ==> gb.Function', where FUNCTION is the
meta-syntactic variable for a function symbol in the current scope.
Unfortunately, that turned out to not be true.  Is there any reason to
not make functions first-class citizens?  That would solve my entire
problem from the root, albeit the considerations given above are
somewhat unrelated and should be considered anyway.

Do you suggest a fourth way of implementing the callback function?  Is
there a standard or ad-hoc way I'm missing?

Thank you in advance.

-- 
 ,= ,-_-. =.  Bruno Félix Rezende Ribeiro (oitofelix) [0x28D618AF]
((_/)o o(\_)) There is no system but GNU;
 `-'(. .)`-'  GNU Linux-Libre is one of its official kernels;
     \_/      All software must be free as in freedom;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://lists.gambas-basic.org/pipermail/user/attachments/20140411/e3a24238/attachment.sig>


More information about the User mailing list