November 08, 2012
On Thursday, 8 November 2012 at 13:19:29 UTC, Jacob Carlborg wrote:
> That syntax looks a bit backwards to me. What if I want to annotate the attribute.

Sorry, I could not resist: http://cdn.memegenerator.net/instances/400x/29863604.jpg

David
November 08, 2012
On Thursday, 8 November 2012 at 13:19:29 UTC, Jacob Carlborg wrote:
> On 2012-11-08 11:56, simendsjo wrote:
>
>> Or
>> struct @foo {}
>> interface @foo {}
>> enum @foo {0
>> etc
>
> That syntax looks a bit backwards to me. What if I want to annotate the attribute.
>
> @serializable struct @foo {}
>
> Looks a bit confusing which is the name of the attribute and the which is the attached annotation.
>
> Vs
>
> @serializable @attribute struct foo {}
>
> No confusion here, "foo" is the name of the attribute, the rest is attached annotations.

I guess it depends. I find it easier to see that it's an attribute, especially when you annotate it. But it's harder to grep for.

Is foo an attribute or not?
  @serializable
  @xmlRoot
  @attribute
  @displayName("foo")
  struct foo {}

Is foo an attribute or not?
  @serializable
  @xmlRoot
  @displayName("foo")
  struct @foo {}

November 08, 2012
On 2012-11-08 17:26, David Nadlinger wrote:

> Sorry, I could not resist:
> http://cdn.memegenerator.net/instances/400x/29863604.jpg

Hehe, exactly :)

-- 
/Jacob Carlborg
November 08, 2012
On 2012-11-08 17:53, simendsjo wrote:

> I guess it depends. I find it easier to see that it's an attribute,
> especially when you annotate it. But it's harder to grep for.
>
> Is foo an attribute or not?
>    @serializable
>    @xmlRoot
>    @attribute
>    @displayName("foo")
>    struct foo {}
>
> Is foo an attribute or not?
>    @serializable
>    @xmlRoot
>    @displayName("foo")
>    struct @foo {}
>

I don't know really. In that bottom example, the struct declartion almost disappears among all the attributes.

-- 
/Jacob Carlborg
November 08, 2012
On Thursday, 8 November 2012 at 17:20:39 UTC, Jacob Carlborg wrote:
> On 2012-11-08 17:53, simendsjo wrote:
>
>> I guess it depends. I find it easier to see that it's an attribute,
>> especially when you annotate it. But it's harder to grep for.
>>
>> Is foo an attribute or not?
>>   @serializable
>>   @xmlRoot
>>   @attribute
>>   @displayName("foo")
>>   struct foo {}
>>
>> Is foo an attribute or not?
>>   @serializable
>>   @xmlRoot
>>   @displayName("foo")
>>   struct @foo {}
>>
>
> I don't know really. In that bottom example, the struct declartion almost disappears among all the attributes.

Yeah.. But at least you'll always know where to look.

@[serializable, xmlRoot, attribute, displayName("foo")]
struct foo {}

@[serializable, xmlRoot, displayName("foo")]
struct @foo {}

but attribute could be required as the last type, and on a line of it's own, giving:

@[serializable, xmlRoot, displayName("foo")]
@attribute
struct foo {}

November 08, 2012
On Wednesday, 7 November 2012 at 23:18:41 UTC, Walter Bright wrote:
> Started a new thread on this.
>
> On 11/7/2012 3:05 AM, Leandro Lucarella wrote:
> > OK, that's another thing. And maybe a reason for listening to
> people having
> > more experience with UDAs than you.
> >
> > For me the analogy with Exceptions is pretty good. The issues
> an conveniences
> > of throwing anything or annotating a symbol with anything
> instead of just
> > type are pretty much the same. I only see functions making
> sense to be accepted
> > as annotations too (that's what Python do with annotations,
> @annotation symbol
> > is the same as symbol = annotation(symbol), but is quite a
> different language).
>
> There's another aspect to this.
>
> D's UDAs are a purely compile time system, attaching arbitrary metadata to specific symbols. The other UDA systems I'm aware of appear to be runtime systems.
>
> This implies the use cases will be different - how, I don't really know. But I don't know of any other compile time UDA system. Experience with runtime systems may not be as applicable.
>
> Another interesting data point is CTFE. C++11 has CTFE, but it was deliberately crippled and burdened with "constexpr". From what I read, this was out of fear that it would turn out to be an overused and overabused feature. Of course, this turned out to be a large error.
>
> One last thing. Sure, string attributes can (and surely would be) used for different purposes in different libraries. The presumption is that this would cause a conflict. But would it? There are two aspects to a UDA - the attribute itself, and the symbol it is attached to. In order to get the UDA for a symbol, one has to look up the symbol. There isn't a global repository of symbols in D. You'd have to say "I want to look in module X for symbols." Why would you look in module X for an attribute that you have no reason to believe applies to symbols from X? How would an attribute for module X's symbols leak out of X on their own?
>
> It's not quite analogous to exceptions, because arbitrary exceptions thrown from module X can flow through your code even though you have no idea module X even exists.

In module sql.d:

    /// For every field marked ["serialize"], add to table
    void saveToDatabase(T)(DBConnection db, T model);

In module json.d:

    /// For every field marked ["serialize"], add to JSON object
    string jsonSerialize(T)(T obj);

In module userinfo.d:

    ["dbmodel"]
    struct UserModel {
        ["serialize"] string username;
        // What do you do if you want this in the database, but not the JSON?
        string password;

        ["serialize"] Content ownedContentOrWhateverThisWebsiteIs;
    }

The only solution to this question is to differentiate "db_serialize" and "json_serialize"; looks a lot like C, doesn't it?

My suggested soluion: @annotation (with [] UDA syntax):

    module sql;
    @annotation enum model;
    @annotation enum serialize;

    module json;
    @annotation enum serialize;

    module userinfo;
    import sql, json;

    [sql.model]
    struct UserModel {
        [sql.serialize, json.serialize] string username;
        [sql.serialize]                 string password;
        [sql.serialize, json.serialize] Content content;
    }

My thoughts,
NMS
November 09, 2012
On Thu, 08 Nov 2012 10:05:30 +0100
Jacob Carlborg <doob@me.com> wrote:
> 
> I think we should only allow user defined types marked with @attribute, i.e.
> 
> @attribute struct foo {}
> @attribute class foo {}
> @attribute interface foo {}
> @attribute enum foo {}
> 
> And so on.
> 

I completely agree. I really hate when languages "play it loose" and leave things up to arbitrary convention. It's like duck/structural typing: the *one* thing I hate about D ranges is that they don't force you to explicitly say "Yes, I *intend* this to be an InputRange" (what are we, Go users?). I don't want to see the same unhelpful sloppiness here.

November 09, 2012
On Thu, Nov 08, 2012 at 10:45:05PM -0500, Nick Sabalausky wrote:
> On Thu, 08 Nov 2012 10:05:30 +0100
> Jacob Carlborg <doob@me.com> wrote:
> > 
> > I think we should only allow user defined types marked with @attribute, i.e.
> > 
> > @attribute struct foo {}
> > @attribute class foo {}
> > @attribute interface foo {}
> > @attribute enum foo {}
> > 
> > And so on.
> > 
> 
> I completely agree. I really hate when languages "play it loose" and leave things up to arbitrary convention. It's like duck/structural typing: the *one* thing I hate about D ranges is that they don't force you to explicitly say "Yes, I *intend* this to be an InputRange" (what are we, Go users?). I don't want to see the same unhelpful sloppiness here.

Actually, I just thought of a solution to the whole duck-typing range thing:

	struct MyRange {
		// Self-documenting: this struct is intended to be a
		// range.
		static assert(isInputRange!MyRange,
			"Dude, your struct isn't a range!"); // asserts

		@property bool empty() { ... }
		@property auto front() { ... }
		int popFront() { ... }
	}

	struct WhatItShouldBe {
		// Junior programmer modifies the function signatures
		// below and the compiler gives him a scolding.
		static assert(isInputRange!WhatItShouldBe,
			"Dude, you just broke my range!"); // passes

		@property bool empty() { ... }
		@property auto front() { ... }
		void popFront() { ... }
	}

	void main() {
		auto needle = "abc";
		auto x = find(WhatItShouldBe(), needle);
	}


T

-- 
I see that you JS got Bach.
November 09, 2012
On Friday, 9 November 2012 at 03:45:11 UTC, Nick Sabalausky wrote:
> the *one* thing I hate about D ranges is that they don't force you to explicitly say "Yes, I *intend* this to be an InputRange" (what are we, Go users?).

Just a note, of course it still wouldn't *force*, but maybe it'd be a good habit to start writing this:

struct myrange {...}
static assert(isInputRange!myrange);

It'd be a simple way to get a check at the point of declaration and to document your intent.


Interestingly, we could also do this if the attributes could run through a template:

[check!isInputRange] struct myrange{}

@attribute template check(something, Decl) {
   static assert(something!Decl);
   alias check = Decl;
}

Same thing, diff syntax.
November 09, 2012
On Thu, 8 Nov 2012 20:17:24 -0800
"H. S. Teoh" <hsteoh@quickfur.ath.cx> wrote:
> 
> Actually, I just thought of a solution to the whole duck-typing range thing:
> 
> 	struct MyRange {
> 		// Self-documenting: this struct is intended to be a
> 		// range.
> 		static assert(isInputRange!MyRange,
> 			"Dude, your struct isn't a range!"); //
> asserts
> 
> 
On Fri, 09 Nov 2012 05:18:59 +0100
"Adam D. Ruppe" <destructionator@gmail.com> wrote:
> 
> Just a note, of course it still wouldn't *force*, but maybe it'd be a good habit to start writing this:
> 
> struct myrange {...}
> static assert(isInputRange!myrange);
> 

Those are only half-solutions as they only prevent false-negatives, not false-positives. Plus, there's nothing to prevent people from forgetting to do it in the first place.

I outlined and implemented a proof-of-concept for a full solution middle of last year:

http://www.semitwist.com/articles/EfficientAndFlexible/MultiplePages/Page5/

The basic gist (and there's definitely still room for plenty of
improvement):

// The General Tool:
string declareInterface(string interfaceName, string thisType)
{
    return `
        // Announce what interface this implements.
        static enum _this_implements_interface_`~interfaceName~`_ =
true;

        // Verify this actually does implement the interface
        static assert(
            is`~interfaceName~`!(`~thisType~`),
            "This type fails to implement `~interfaceName~`"
        );
    `;
}

// Sample usage:
template isFoo(T)
{
    immutable bool isFoo = __traits(compiles,
    (){
        T t;
        static assert(T._this_implements_interface_Foo_);
	t.fooNum = 5;
	int x = t.fooFunc("");
        // Check everything else here
    });
}

struct MyFoo
{
    // Can probably be more DRY with fancy trickery
    mixin(declareInterface("Foo", "MyFoo"));

    int fooNum;
    int fooFunc(string a) {...}
}

What I'd really like to see is a way to implement declareInterface so
that the isFoo is replaced by an ordinary "interface Foo {...}",
which MyFoo's members are automatically checked against. I suspect that
should be possible with some fancy metaprogramming-fu.