January 09, 2009
"Miles" <_______@_______.____> wrote in message news:gk7fau$f38$1@digitalmars.com...
> Nick Sabalausky wrote:
>> Well, like I said, *If* we were to get overload-on-return-value. Not that
>> I'm itching for it or anything. I've just seen the idea discussed before
>> and
>> if it hypothetically were to happen, then the above could work as a
>> getter
>> equivilent.
>
> Ok. But I think such feature would create a mess. For example:
>
> int    func1() { ... }
> char[] func1() { ... }
>
> void   func2(int x) { ... }
> void   func2(char[] x) { ... }
>
> func2(func1()); // what is the expected behavior?
>
> When you are inferring types, you need somewhere to anchor the compiler decision, either on the sender or on the receiver side.

Like I said, I'm neither advocating nor condemning overload-on-return-value.


January 09, 2009
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gk7nij$rlo$1@digitalmars.com...
>
>
> Michiel Helvensteijn wrote:
>> [Condensed: syntax sucks, let's introduce more!]
>
> I might be old fashioned (get offa mah lawn!), but I've always found something like the following quite acceptable:
>
> class Foo
> {
>     mixin(properties
>     ("
>         rw int bar;
>         ro float baz;
>         wo Foo zyzzy;
>     "));
> }
>
> I know I had a CTFE function lying around that would parse that and generate the code for it.  I agree that C# has a nicer syntax for this, but with CTFE/templates and string mixins, we can have whatever syntax we damn well want.
>
> Hell, I used this in a prototype game engine to generate CVars; it'd generate the properties, the backing store, the hooking code, event registration, etc.  One line generated about 10-20 lines of boilerplate for me; C# can't do that!
>
> Why change the language when you can just abuse it's already-existing features? :D
>
>   -- Daniel "downs is my hero"

String mixins are very powerful, and certainly welcome IMO, but they involve dynamically generating code by algorithmically splicing together little text snippets, and that's just very hack-ish. It's literally just like using classic-style ASP or PHP. That was too clumbsy even for the already-clumbsiness-embracing world of the web; that's why they're moving towards proper page-templating engines. I see the role of string mixins as being a handy way to hack together a piece of advanced functionality until a better more proper way comes along.


January 09, 2009
dsimcha wrote:
> == Quote from Daniel Keep (daniel.keep.lists@gmail.com)'s article
>> Why change the language when you can just abuse it's already-existing
>> features? :D
>>    -- Daniel "downs is my hero"
> 
> This is precisely the attitude that left C++ with all of the cruft and baggage it
> has.  Yes, if something can be implemented *elegantly, efficiently, and with clean
> syntax* in a library, then it doesn't belong in the core language.  Yes, powerful
> language features like templates, mixins, operator overloading, etc. are great for
> abusing when you need something that's not universal enough to be in the core
> language.

Well I'm not so sure about that. In fact I'd go as far as saying you're contradicting yourself. The cruft and baggage is exactly left by unsuccessful language features that had to stay because, well, they were IN the language. For a good while, C++ has been rather liberal in adopting new and risky language features (exceptions, multiple inheritance, templates...) In contrast, for most of its existence, C++ has had an extremely thin library. An example of a bad library from the old days is iostreams, but hardly anyone considers that a major issue. It's not cruft and it's not baggage. It just sucks. :o)

So your own logic inexorably leads to a conclusion opposite to your hypothesis: it's best to keep the language lean and keep one's options open, lest cruft and baggage will accumulate.

Of course that, taken to an extreme, can lead to contortions and can do more harm than good. So moderation is likely the best way to go.

> The flip side is that, the more you rely on libraries (whether your personal
> snippet library or an "official" library) that use hacks like this, the more
> you're building a house of cards.

That's a bit odd. Are you saying that libraries are inherently less reliable than language features?

> When you build hacks on top of other hacks, and
> build these on top of still more hacks (think STL), you're basically asking ugly
> syntax, odd corner cases, and the exposure of obscure implementation bugs.  This
> is why things like arrays, strings and delegates belong in the core language.
> Since properties are just as universal, I believe the same argument can be made
> for them.

When I "think STL" I'm thinking of the best-defined library of general containers and algorithms. No other library I know goes to a longer length at defining its own behavior. Knowing STL makes me look with a rather critical eye at the loosely-defined libraries that accomplish (often sloppily) similar tasks usually featured with other languages.


Andrei
January 09, 2009
== Quote from Andrei Alexandrescu (SeeWebsiteForEmail@erdani.org)
> Well I'm not so sure about that. In fact I'd go as far as saying you're
> contradicting yourself. The cruft and baggage is exactly left by
> unsuccessful language features that had to stay because, well, they were
> IN the language. For a good while, C++ has been rather liberal in
> adopting new and risky language features (exceptions, multiple
> inheritance, templates...) In contrast, for most of its existence, C++
> has had an extremely thin library. An example of a bad library from the
> old days is iostreams, but hardly anyone considers that a major issue.
> It's not cruft and it's not baggage. It just sucks. :o)
> So your own logic inexorably leads to a conclusion opposite to your
> hypothesis: it's best to keep the language lean and keep one's options
> open, lest cruft and baggage will accumulate.
> Of course that, taken to an extreme, can lead to contortions and can do
> more harm than good. So moderation is likely the best way to go.

I will admit that cruft and baggage were probably poor word choices to describe what I meant.  I really meant things like odd syntax and weird corner cases caused by not having the core language know about very basic, frequently used things like arrays and strings.

> > The flip side is that, the more you rely on libraries (whether your personal snippet library or an "official" library) that use hacks like this, the more you're building a house of cards.
> That's a bit odd. Are you saying that libraries are inherently less reliable than language features?

In a way, yes.  When building a feature into a language, you can do literally *anything* that is computationally feasible, such as define new syntax, make the compiler "know" about the feature at a high level, display good high-level error messages, etc.  When you're defining something in a library, you're limited by existing constructs.  Sometimes those existing constructs are enough to do what you want cleanly and elegantly.  Sometimes (as in the OP's example) you have to resort to hacks.  My point is that, when you have a low-level library feature A that's kind of a hack and does strange things in certain edge/error/unanticipated cases, and then you build a high-level library feature B on top of A using still more hacks, what are the odds that if something goes wrong with B, anyone will have any clue why?  What are the odds that B won't have some frustrating, arbitrary limitations?

> > When you build hacks on top of other hacks, and
> > build these on top of still more hacks (think STL), you're basically asking ugly
> > syntax, odd corner cases, and the exposure of obscure implementation bugs.  This
> > is why things like arrays, strings and delegates belong in the core language.
> > Since properties are just as universal, I believe the same argument can be made
> > for them.
> When I "think STL" I'm thinking of the best-defined library of general containers and algorithms. No other library I know goes to a longer length at defining its own behavior. Knowing STL makes me look with a rather critical eye at the loosely-defined libraries that accomplish (often sloppily) similar tasks usually featured with other languages. Andrei

Yes, STL (and Boost, etc.) are very high-quality libraries.  The problem is that, because the core language doesn't "understand" anything in them, there's no shortage of things like clumsy syntax, inscrutible error messages for the tiniest errors, etc.  This is not to say that all, or even most, of STL or Boost belong in the core C++ language, just the features that are both heavily used and would benefit greatly from the core language "understanding" them.
January 09, 2009

Nick Sabalausky wrote:
> String mixins are very powerful, and certainly welcome IMO, but they involve dynamically generating code by algorithmically splicing together little text snippets, and that's just very hack-ish. It's literally just like using classic-style ASP or PHP. That was too clumbsy even for the already-clumbsiness-embracing world of the web; that's why they're moving towards proper page-templating engines. I see the role of string mixins as being a handy way to hack together a piece of advanced functionality until a better more proper way comes along. 

I think the comparison is a bit loose; the problem with ASP and PHP was the way most people mixed processing logic and display.  Here, there's a relatively clean separation.

Yes, a language-level construct for this would be nice, but where do you draw the line?

Personally, I'm a big believer in generic constructs.  Let's pretend for a moment that we've got AST macros, and can specify that our macro uses { } instead of ( )...

properties
{
    rw int foo;
    ro float bar;
}

That might as well be a language construct!  And D isn't as bad as C/C++ when it comes to inscrutible error messages; we at least have pragma(msg), although I admit it would be nice to have more control over where the compiler says an error comes from, and what the code responsible is.

At the end of the day, my job is to make a computer do stuff.  If string mixins help me reach that goal quicker [1], then I'm all for it.

 -- Daniel

[1] Obviously, I don't mean "at all costs;" something like:

  mixin(/* a long, complex expression that produces a string */);

is pretty obviously a bad idea for exactly the reasons you gave above. Something like:

  mixin(hhfk("kjiq9238*)&70394{"));

is also a bad idea, for rather obvious reasons.
January 10, 2009
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gk8j4h$29fm$1@digitalmars.com...
>
>
> Nick Sabalausky wrote:
>> String mixins are very powerful, and certainly welcome IMO, but they involve dynamically generating code by algorithmically splicing together little text snippets, and that's just very hack-ish. It's literally just like using classic-style ASP or PHP. That was too clumbsy even for the already-clumbsiness-embracing world of the web; that's why they're moving towards proper page-templating engines. I see the role of string mixins as being a handy way to hack together a piece of advanced functionality until a better more proper way comes along.
>
> I think the comparison is a bit loose; the problem with ASP and PHP was the way most people mixed processing logic and display.  Here, there's a relatively clean separation.
>

It's not so much an issue of logic vs display (if you're using a somewhat literal definition of "display"), as it is an issue of proper ways to dynamically generate code regardless of whether the generated output is a "display" description or a description of yet more logic (ex, generating client-side JavaScript using classic ASP/PHP techniques is still rightly considered just as bad as if HTML were being generated).

With that in mind, how do D string mixins have more logic/output separation than typical ASP or PHP? The actual implementation of the string-generating function (or template) still mixes logic with output.

Suppose you wanted to make a mixin that generated a bunch of int declarations from a list of names. How would you implement that? With current D, it would have to be something like this:

/ / Pseudocode
declareStuff(string[] names) // template or CTFE
{
    // Template-style would be mostly the same,
    // but maybe slightly more functional than imperative.
    string str;
    foreach(name; names)
       str ~= "int "~name~";\n"; // \n helps with debugging
    return str;
}

Now compare that to a fairly typical method for generating a list in classic-ASP/PHP:

/ / Pseudocode
generateList(string[] listElements)
{
    string str= "<ul>";
    foreach(elem; listElements)
       str ~= "<li>"~elem~"</li>\n";
    return str~"</ul>";
}

It's practically the same code, except that the web development world has been discovering that's in a bad style that leads to problems.

Although, maybe string mixins could make use of proper logic/output separation if we had better CTFE. Then we could use something like ANTLR's StringTemplate lib. But maybe that would lead to unnecessarily long compile times?

In any case, whenever I see "mixin(...);", even in my own code, I always think "hack". That's fine for obscure special-domain tools, but for something as common and as general as properties, it just comes across as a big kludge.

> Yes, a language-level construct for this would be nice, but where do you draw the line?
>

IMO, Somewhere beyond "property syntax" ;-)

> Personally, I'm a big believer in generic constructs.  Let's pretend for a moment that we've got AST macros, and can specify that our macro uses { } instead of ( )...
>
> properties
> {
>     rw int foo;
>     ro float bar;
> }
>

If we had AST macros, and creating them was significantly cleaner than creating string mixins, then that would certainly reduce the need for language-level things like properties.

However, I would still very much insist that something as common as properties would, at the very least, be part of the standard library. It wouldn't be good for the language to have twenty different custom property-syntax libs floating around.


January 10, 2009
Nick Sabalausky:
> In any case, whenever I see "mixin(...);", even in my own code, I always think "hack". That's fine for obscure special-domain tools, but for something as common and as general as properties, it just comes across as a big kludge.

I agree. String mixin are generally near-unreadable, and I hate to debug them. So it's better to use them as little as possible.
If many D programs show a very common pattern (like certain usages of properties) it becomes a candidate to be included into the compiler and not done with string mixings anymore.
(This also means you can see string mixings as feature laboratories: that is tests of features that may be added to future versions of the language. Just like plugins in Firefox).

Bye,
bearophile
January 10, 2009
Daniel Keep wrote:
> 
> 
> Michiel Helvensteijn wrote:
>> [Condensed: syntax sucks, let's introduce more!]
> 
> I might be old fashioned (get offa mah lawn!), but I've always found something like the following quite acceptable:
> 
> class Foo
> {
>     mixin(properties
>     ("
>         rw int bar;
>         ro float baz;
>         wo Foo zyzzy;
>     "));
> }
> 
	Note that this is a very limited use for properties. Defining
properties isn't just a question of access control (read/write, read
only, or write only). It is also a way to execute arbitrary code
each time the value is changed (or accessed), or to create
properties that don't correspond to actual data fields (complex
module and argument come to mind). How would you do that with
mixins? (Not that it would be impossible, but the syntax would
probably be horrible).

		Jerome
- --
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr
January 10, 2009

Jérôme M. Berger wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Daniel Keep wrote:
>>
>> Michiel Helvensteijn wrote:
>>> [Condensed: syntax sucks, let's introduce more!]
>> I might be old fashioned (get offa mah lawn!), but I've always found
>> something like the following quite acceptable:
>>
>> class Foo
>> {
>>     mixin(properties
>>     ("
>>         rw int bar;
>>         ro float baz;
>>         wo Foo zyzzy;
>>     "));
>> }
>>
> 	Note that this is a very limited use for properties. Defining
> properties isn't just a question of access control (read/write, read
> only, or write only).

For me, it *was* a case of access-control... at least, it was about 80% of the time.

I'm a fan of interface-heavy design: make an interface for every distinct kind of functionality and pack them all together.  That means I end up with a metric buttload (equivalent to about 42 imperial piles) of properties.

And most of them were just accessors that needed to be in the interface; hence the functionality of the mixin.

> It is also a way to execute arbitrary code
> each time the value is changed (or accessed), ...

It's been a while since I used the code, and honestly I can't seem to track it down, but I recall that I could do this:

  mixin(properties(" rw int bar; "));

  protected void bar_onSet(int newValue) { ... }

There was also an *_onGet, and you could block setting a property by throwing an exception, I believe.

Granted, this doesn't cover every possible use-case, but then it's not supposed to; it's supposed to make the 90% easier.  It still did the assignment, since I felt you shouldn't be making properties that have a setter that doesn't set anything...

> ... or to create
> properties that don't correspond to actual data fields (complex
> module and argument come to mind).

If the property doesn't correspond to a physical field, then you're going to have to write the code to handle it from scratch.  And no matter WHAT you do, it's eventually going to boil down to one or more functions.  Which is EXACTLY how they currently work.

What would be the point of making a special syntax when you can already do that? :P

> How would you do that with
> mixins? (Not that it would be impossible, but the syntax would
> probably be horrible).
> 
> 		Jerome

On a somewhat related note, I've often pondered writing a very limited D parser in CTFE to do this sort of thing more easily, but never got around to it, nevermind the CTFE memory bugs...

  -- Daniel
January 10, 2009
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:gk9v33$1bvu$1@digitalmars.com...
>
>
> Jérôme M. Berger wrote:
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>> Daniel Keep wrote:
>>>
>>> Michiel Helvensteijn wrote:
>>>> [Condensed: syntax sucks, let's introduce more!]
>>> I might be old fashioned (get offa mah lawn!), but I've always found something like the following quite acceptable:
>>>
>>> class Foo
>>> {
>>>     mixin(properties
>>>     ("
>>>         rw int bar;
>>>         ro float baz;
>>>         wo Foo zyzzy;
>>>     "));
>>> }
>>>
>> Note that this is a very limited use for properties. Defining properties isn't just a question of access control (read/write, read only, or write only).
>
> For me, it *was* a case of access-control... at least, it was about 80% of the time.
>
> I'm a fan of interface-heavy design: make an interface for every distinct kind of functionality and pack them all together.  That means I end up with a metric buttload (equivalent to about 42 imperial piles) of properties.
>
> And most of them were just accessors that needed to be in the interface; hence the functionality of the mixin.
>
> > It is also a way to execute arbitrary code
>> each time the value is changed (or accessed), ...
>
> It's been a while since I used the code, and honestly I can't seem to track it down, but I recall that I could do this:
>
>   mixin(properties(" rw int bar; "));
>
>   protected void bar_onSet(int newValue) { ... }
>
> There was also an *_onGet, and you could block setting a property by throwing an exception, I believe.
>
> Granted, this doesn't cover every possible use-case, but then it's not supposed to; it's supposed to make the 90% easier.  It still did the assignment, since I felt you shouldn't be making properties that have a setter that doesn't set anything...
>
> > ... or to create
>> properties that don't correspond to actual data fields (complex
>> module and argument come to mind).
>
> If the property doesn't correspond to a physical field, then you're going to have to write the code to handle it from scratch.  And no matter WHAT you do, it's eventually going to boil down to one or more functions. Which is EXACTLY how they currently work.
>
> What would be the point of making a special syntax when you can already do that? :P
>


Same reason we have "while" and "foreach" in addition to "for".


> > How would you do that with
>> mixins? (Not that it would be impossible, but the syntax would
>> probably be horrible).
>>
>> Jerome
>
> On a somewhat related note, I've often pondered writing a very limited D parser in CTFE to do this sort of thing more easily, but never got around to it, nevermind the CTFE memory bugs...
>
>   -- Daniel