Function calls

Gerrit Wichert gw at green-stores.de
Fri Jan 29 14:22:11 PST 2010


Hello,

I think the biggest part of our problem with @property is, that we are
using the wrong words. I'm no native english speaker so it  may be that
i'm totaly wrong with this,  but that's my impression. When i hear the
word property i'm thinking: "ok, this is a well defined part of the
internal state of that object instance that i'm allowed to  interact
with". 

That's what i think a property is. It is not about parentheses or not
parentheses. It is not about just marking functions to change their call
behaviour.

I think a property should be about *first* naming and defining a
distinct part of the object state and thereafter *optionally* defining
how to deal with it.

I really  don't want to talk much about syntax  but  i like the  way 
Moose  has solved this problem for  Perl5.  Even if its syntax is not
compatible to a C derived language language like D (btw. why not?), a
quick skim of its documentation  may be a source of inspiration. It
clearly was for me.

http://search.cpan.org/~drolsky/Moose-0.94/lib/Moose.pm

The coolest thing about Moose is, that it doesn't  change the language
of Perl5 in any way. For attributes (their name for properties) it just
implements  a declarative syntax that is valid perl code and executed at
compile time to define fields and accessor functions.

so a simple
    has 'x' => (is => 'rw', isa => 'Int');
just defines a field that can hold an integer and two accessor functions
x() and x(int). The name of  the  real field and how it is stored is
adjustable but defaults to the way perl objects are normaly constructed.

    has 'x' => (is => 'ro', isa => 'Int');
just omits constructing a write accessor.

To be exact at this a readonly property doesn't mean it is const, it
means that you don't have a write accessor and therefore can't
substitute its content. You can get a mutable subobject or struct via a
read accesseor and manipulate it via its own property accessors but you
can't substitute it since you have no write accessor. If you don't want
to let the client manipulate intenal state via a read accessor of a
complex property just make it return a const subobject.   

Semantically this turns a property into a little sub-class even if it is
not defined as such. It is implemented as old school fields and accessor
functions. But they are auto generated until you feel the need to define
them explicitly. There are much more ideas in Moose that may be
applicable to D that i won't go any deeper in here. Please skim it's 
documentation if you're  interested.  For me it has  turned Perl into
something beautiful while being extremly flexible.

But I don't want to advertise any Perl, just hoping the idees behind
Moose can be helpful. So back to D.

The simplest property definition i can think of ist this:

class c {
    public:
    int a;
}

This can be interpreted as a property with name 'a' that has compiler
generated accessor functions int a(), and a (int) or int a(int) .The
compiler can not only auto generate them, it can also opimize them away.
So at the end of the day a field can be seen as an optimized property.
This implicates that i should be able to access fields using accessor
function syntax.
Yes, i really mean someting like x = c.a() or c.a( x) also for field
access. Even auto old = c.a( x) may be usefull. I think this can be
essential for templates or meta programming.
Syntax like x = c.a or c.a = x is cute but should be rewritten to the
above by the compiler and then optimized away in case of auto-generated
accessors.

The whole talk about using parentheses or not  for accessor functions, 
just to  better distinguish accessors from real fields when reading D
sources i have a really simple solution for. Just conceptually get rid
of real fields  in objects. Then we don't have to distinguish. And if
"int a;" in  a class definition simply defines a lightweight rw property
that internally is implemented by the compiler as a field, we get the
benefits of real properties for each field without changing one line of
already written source code. The danger of confusing field access with a
function call omitting empty parentheses vanishes as well because every
field access is now consequently a call of a property accessor even when
optimized away. So function calls can safely omit empty parentheses
without being ambigious.   

Then later we can think about creating a DSL that helps us to *declare*
more complex  types of properties and have  the compiler construct the
implicit parts at compile time. For instance i can think of a boolean
property that has a toggle accessor.

We shouldn't compose our classes from fields and functions that we
declare to be called with or without parentheses.
We should compose our classes from properties we declare (public, privat
or whatever) and let the compiler do the boring work for us.   


Now to your problem with byLine:


> > Some said it should be stdin.byLine(), some others said it should be
stdin.byLine. They invoked contradictory rules that led to contradictory
conclusions.

If byLine  internally constructs a new range instance that happens to
use stdin for iterating by line, this to me ist clearly a function. And
then the normal rules for calling a function in the D language must
apply. This has nothing to do with properties.

If you have a single ByLineRange instance stored in stdin that is simply
handed out by the byLine  function,  than  this  can be seen  as  a
getter function of a byLine property and *both* forms should be applicable.

So, that is my opinion about properties. I hope it makes some sense to
you or is helpful to anyone.

--
Gerrit

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100129/1a10b3cd/attachment.html>


More information about the Digitalmars-d mailing list