March 05, 2011
On 3/5/2011 4:42 PM, Michel Fortin wrote:
> I've always been on the fence about this. I find it useful too, and I
> like the visual effect of optional parenthesis. But returning anything
> that is callable make things ambiguous to the reader and can even bring
> bugs when it comes to generic programming; and ambiguity and bugs are
> things I really don't want to see.
>
>

So?  Make the semantics of @property one-way instead of two-way and make it a best practice to always use it in generic code.  @property functions **can't** be called with (), but ()s are **optional** for stuff not marked @property.
March 05, 2011
On 2011-03-05 16:49:30 -0500, dsimcha <dsimcha@yahoo.com> said:

> On 3/5/2011 4:42 PM, Michel Fortin wrote:
>> I've always been on the fence about this. I find it useful too, and I
>> like the visual effect of optional parenthesis. But returning anything
>> that is callable make things ambiguous to the reader and can even bring
>> bugs when it comes to generic programming; and ambiguity and bugs are
>> things I really don't want to see.
> 
> So?  Make the semantics of @property one-way instead of two-way and make it a best practice to always use it in generic code.  @property functions **can't** be called with (), but ()s are **optional** for stuff not marked @property.

There's still a small ambiguity with functions returning callable types. For instance, if you have a template defining a property of a parametrized type, forgetting to add @property to the getter could result in buggy behaviour with a callable type but work fine with everything else. Is making parenthesis optional worth making this kind of bug easier to slip by, I wonder.

That said, () being optional doesn't help you use setters with chaining. You'd have to not label your setters with @property for them to work with chaining, unless you want to play with a lot of nested parenthesis.

	(((Graph().title = abc).xTitle = def).yTitle = hij);

Wow, that looks almost like Objective-C!

This discussion should probably happen somewhere else than the announcement forum though.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

March 05, 2011
On 3/5/2011 5:51 PM, Michel Fortin wrote:
> There's still a small ambiguity with functions returning callable types.
> For instance, if you have a template defining a property of a
> parametrized type, forgetting to add @property to the getter could
> result in buggy behaviour with a callable type but work fine with
> everything else. Is making parenthesis optional worth making this kind
> of bug easier to slip by, I wonder.

This is an extreme corner case, especially if a one-way semantic @property syntax is available to work around it.  The percentage of functions that return callables is very small, and of these the percentage that would forget @property is probably very small.  I'd rather bug-proneness in a ridiculous corner case than breaking tons of existing code code and losing a nice feature in the common case.

>
> That said, () being optional doesn't help you use setters with chaining.
> You'd have to not label your setters with @property for them to work
> with chaining, unless you want to play with a lot of nested parenthesis.
>
> (((Graph().title = abc).xTitle = def).yTitle = hij);
>
> Wow, that looks almost like Objective-C!

Right.  The point is that I can do the same thing with either property syntax or with chaining.  The choice is up to me as the caller, if the API designer is ok with allowing this choice.
March 06, 2011
dsimcha:

> I'd rather bug-proneness in a ridiculous corner case than breaking tons of existing code code and losing a nice feature in the common case.

That "existing code" will cause troubles to D2 development. People get attached to wrong/deprecated features.

Bye,
bearophile
March 06, 2011
"Robert Jacques" <sandford@jhu.edu> wrote in message news:op.vrvz7do126stm6@sandford.myhome.westell.com...
> On Sat, 05 Mar 2011 13:42:32 -0500, bearophile <bearophileHUGS@lycos.com> wrote:
>
>> dsimcha:
>>
>>> I've done some major updating of my Plot2kill plotting library lately,
>>
>> I see code that wants named arguments :-)
>>
>> 65     auto sleepinessFig = Figure(sleepinessPlot)
>> 66         .title("Sleepiness Survey")
>> 67         .yLabel("Sleepiness Rating")
>> 68         .xLabel("Activity")
>> 69         .legendLocation(LegendLocation.right)
>> 70         .horizontalGrid(true)
>> 71         .xTickLabels(
>> 72             iota(3),
>> 73             ["In Meeting", "On Phone", "Coding"]
>> 74         );
>>
>> Bye,
>> bearophile
>
> Why? Each of those arguments should be able to be set after creation. So given DRY principals, method chaining is the way to go. Besides, Figure takes a variable number of plot arguments, which means you couldn't support default arguments (at least with the current syntax).

I've also attached this as a file in case it's hard to read on the NG clients:

--------------------------------------------------
// Tested on DMD 2.050
import std.variant;

template Optional(T)
{
    alias Algebraic!(T) Optional;
}

template notSpecified(T)
{
    Optional!T notSpecified;
}

Optional!T specified(T)(T val)
{
    return Optional!T(val);
}

void setIfSpecified(T)(ref T target, Optional!T val)
{
    if(val.hasValue())
        target = val.get!T();
}

struct Plot
{
    string name;
}

struct Fancy
{
    string memberVar1;
    int[]  memberVar2;
    bool   memberVar3;

    // I don't know why I need this or why it seems to need to be called
manually.
    const int opCmp(ref const Fancy other)
    {
        return
            memberVar1 == other.memberVar1 &&
            memberVar2 == other.memberVar2 &&
            memberVar3 == other.memberVar3;
    }
}

struct Figure
{
    Plot   plot;
    string title;
    bool   horizontalGrid;
    Fancy  fancy;

    this(Plot plot)
    {
        this.plot = plot;
    }

    ref Figure set(
        Optional!string title          = notSpecified!string,
        Optional!bool   horizontalGrid = notSpecified!bool,
        Optional!Fancy  fancy          = notSpecified!Fancy
    )
    {
        setIfSpecified!string(this.title,          title);
        setIfSpecified!bool  (this.horizontalGrid, horizontalGrid);
        setIfSpecified!Fancy (this.fancy,          fancy);
        return this;
    }
}

void main()
{
    // All of the ugly 'specified()' could be eliminated if there
    // were some sort of opImplicitCast

    auto fig = Figure(Plot("My Plot"))
        .set(
            specified("My Title"),
            specified(true),
            specified(Fancy("Foo", [1,2,3], true))
        );

    assert(fig.title == "My Title");
    assert(fig.horizontalGrid == true);
    assert(fig.fancy.opCmp( Fancy("Foo", [1,2,3], true) ));

    fig = fig.set().set().set();
    assert(fig.title == "My Title");
    assert(fig.horizontalGrid == true);
    assert(fig.fancy.opCmp( Fancy("Foo", [1,2,3], true) ));

    fig = fig.set( specified("New title name") );
    assert(fig.title == "New title name");
    assert(fig.horizontalGrid == true);
    assert(fig.fancy.opCmp( Fancy("Foo", [1,2,3], true) ));

    // The above maybe aren't so special as-is, but with named arguments
    // the following could be uncommented and used:
    /+

    fig = fig.set(
        fancy: specified(Fancy("Bar", [7,9,12], false)),
        title: specified("Another Title")
    );
    assert(fig.title == "Bar");
    assert(fig.horizontalGrid == true);
    assert(fig.fancy.opCmp( Fancy("Bar", [7,9,12], false) ));

    +/
}

--------------------------------------------------



March 06, 2011
On 2011-03-05 18:42:26 -0500, dsimcha <dsimcha@yahoo.com> said:

> This is an extreme corner case, especially if a one-way semantic @property syntax is available to work around it.  The percentage of functions that return callables is very small, and of these the percentage that would forget @property is probably very small.  I'd rather bug-proneness in a ridiculous corner case than breaking tons of existing code code and losing a nice feature in the common case.

The percentage of functions that return a callable is very small until you go to template land. I can easily make a container or a range of delegates, and if someone somewhere forgot to make 'front' a property in the container, in the container's range or in one of the filter range layered on top of it, then writing 'front()' to call the front delegate becomes unreliable. Is it a corner case? Yes. Is it ridiculous to expect the language to detect rare but hard to find bugs? No. Is it worth it in this case? I think so.


>> That said, () being optional doesn't help you use setters with chaining.
>> You'd have to not label your setters with @property for them to work
>> with chaining, unless you want to play with a lot of nested parenthesis.
>> 
>> (((Graph().title = abc).xTitle = def).yTitle = hij);
>> 
>> Wow, that looks almost like Objective-C!
> 
> Right.  The point is that I can do the same thing with either property syntax or with chaining.  The choice is up to me as the caller, if the API designer is ok with allowing this choice.

Allowing optional '()' and allowing optional '=' are two different things. But contrary to optional '()' I don't see much of a problem with '=' as there's no ambiguity possible. It just looks a little strange to have a @property attribute and not restrict the property assignment syntax to it.

-- 
Michel Fortin
michel.fortin@michelf.com
http://michelf.com/

March 06, 2011
"Michel Fortin" <michel.fortin@michelf.com> wrote in message news:ikum9a$2agj$1@digitalmars.com...
> On 2011-03-05 18:42:26 -0500, dsimcha <dsimcha@yahoo.com> said:
>
>> This is an extreme corner case, especially if a one-way semantic @property syntax is available to work around it.  The percentage of functions that return callables is very small, and of these the percentage that would forget @property is probably very small.  I'd rather bug-proneness in a ridiculous corner case than breaking tons of existing code code and losing a nice feature in the common case.
>
> The percentage of functions that return a callable is very small until you go to template land. I can easily make a container or a range of delegates, and if someone somewhere forgot to make 'front' a property in the container, in the container's range or in one of the filter range layered on top of it, then writing 'front()' to call the front delegate becomes unreliable. Is it a corner case? Yes. Is it ridiculous to expect the language to detect rare but hard to find bugs? No. Is it worth it in this case? I think so.
>

Along those lines, I'll point out that the idea of a range of delegates is not a stretch at all: it could make a lot of sense for a GUI API, for instance. The .NET windowing API handles callbacks as collections of delegates and I always thought that worked fairly well (and seems functionally equivalent to Qt's system of signals and slots, AIUI).


March 06, 2011
"Nick Sabalausky" <a@a.a> wrote in message news:ikuome$2edr$1@digitalmars.com...
> "Michel Fortin" <michel.fortin@michelf.com> wrote in message news:ikum9a$2agj$1@digitalmars.com...
>> On 2011-03-05 18:42:26 -0500, dsimcha <dsimcha@yahoo.com> said:
>>
>>> This is an extreme corner case, especially if a one-way semantic @property syntax is available to work around it.  The percentage of functions that return callables is very small, and of these the percentage that would forget @property is probably very small.  I'd rather bug-proneness in a ridiculous corner case than breaking tons of existing code code and losing a nice feature in the common case.
>>
>> The percentage of functions that return a callable is very small until you go to template land. I can easily make a container or a range of delegates, and if someone somewhere forgot to make 'front' a property in the container, in the container's range or in one of the filter range layered on top of it, then writing 'front()' to call the front delegate becomes unreliable. Is it a corner case? Yes. Is it ridiculous to expect the language to detect rare but hard to find bugs? No. Is it worth it in this case? I think so.
>>
>
> Along those lines, I'll point out that the idea of a range of delegates is not a stretch at all: it could make a lot of sense for a GUI API, for instance. The .NET windowing API handles callbacks as collections of delegates and I always thought that worked fairly well (and seems functionally equivalent to Qt's system of signals and slots, AIUI).
>

s/callbacks/events/   (Although I guess it works either way.)


March 06, 2011
The GUI lib DFL uses callbacks as well IIRC. Probably not a range of them though. I do know that in Qt you can have a signal attached to multiple slots.
March 06, 2011
On Sat, 05 Mar 2011 13:31:22 -0500, dsimcha wrote:

> On 3/5/2011 1:27 PM, Lars T. Kyllingstad wrote:
>> Does this mean that it can save to vector formats now, or just that you intend to add that functionality?  EPS would be awesome, because it's pretty much the only thing you can use directly with LaTeX.  (Yes, pdfLaTeX accepts many other formats, but many scientific journals still require you to provide EPS figures.)
>>
>> Of course, one can usually convert losslessly between the various vector formats, but it would be most convenient if Plot2kill could save directly to EPS, PDF and SVG.
>>
>> -Lars
> 
> ?????  Plot2kill (the GTK version) has been able to save to EPS, SVG, PDF, PNG, JPEG and BMP since I switched the GTK port to use the Cairo backend last July.  (The DFL port can only do BMP and PNG.)  If this is a killer feature for you, I apologize for not publicizing it more back then.  I've been eating my own dogfood since then.  All of the graphs in my Ph.D. proposal and a publication manuscript I'm working on are Plot2Kill rendered and saved in vector formats.

Oh, I didn't know that.  That's very cool!  I can't remember seeing an announcement of this feature from you, nor did I expect the feature to be there, so I guess I just didn't look that closely for it. :)

-Lars