{"action":"created","issue":{"url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/282","labels_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/282/labels{/name}","comments_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/282/comments","events_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/282/events","html_url":"https://github.com/CausalityLtd/ponyc/issues/282","id":101324711,"number":282,"title":"fields in traits & interfaces?","user":{"login":"ryanai3","id":8884501,"avatar_url":"https://avatars.githubusercontent.com/u/8884501?v=3","gravatar_id":"","url":"https://api.github.com/users/ryanai3","html_url":"https://github.com/ryanai3","followers_url":"https://api.github.com/users/ryanai3/followers","following_url":"https://api.github.com/users/ryanai3/following{/other_user}","gists_url":"https://api.github.com/users/ryanai3/gists{/gist_id}","starred_url":"https://api.github.com/users/ryanai3/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ryanai3/subscriptions","organizations_url":"https://api.github.com/users/ryanai3/orgs","repos_url":"https://api.github.com/users/ryanai3/repos","events_url":"https://api.github.com/users/ryanai3/events{/privacy}","received_events_url":"https://api.github.com/users/ryanai3/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-08-17T02:29:55Z","updated_at":"2015-08-27T04:56:10Z","closed_at":null,"body":"Something I've come across in developing some stuff in pony.\r\nI think it would be really useful to be able to declare fields in traits & interfaces - especially since that's the primary method through which code-sharing is done (no inheritance). \r\n\r\nAt the moment the following doesn't compile: \r\n```pony\r\n//Doesn't Compile\r\ntrait Foo\r\n  let _field1: Set[U32] // It's a trait, so we can have private fields\r\n  fun ref addNum(num: U32) =>\r\n    //Do stuff\r\n    _field1.set(num)\r\n  fun ref removeNum(num: U32) =>\r\n    //Do stuff\r\n    _field1.unset(num)\r\n\r\ninterface Bar\r\n  //Currently no private methods in interfaces - following same convention for fields\r\n  var field2: Set[String] = Set[String].create()\r\n  fun ref addString(str: String) =>\r\n    //Do stuff\r\n    field2.set(str)\r\n  fun ref removeString(str: String) =>\r\n    //Do stuff\r\n    field2.unset(str)\r\n\r\nclass Impl is Foo\r\n  let _field1: Set[U32] = Set[U32].create()\r\n\r\nclass Impl2 is (Foo & Bar)\r\n  let _field1: Set[U32] = Set[U32].create()\r\n  var field2: Set[String] = Set[String].create()\r\n```\r\n\r\nConceptually, you can treat it as sugar for the following ugly which does compile.\r\n\r\n```pony\r\n//Compiles\r\ntrait Foo\r\n  fun ref _getField1(): Set[U32]\r\n  fun ref addNum(num: U32) =>\r\n  //Do Stuff\r\n    _getField1().set(num)\r\n  fun ref removeNum(num: U32) =>\r\n  //Do Stuff\r\n    _getField1().unset(num)\r\n\r\ninterface Bar\r\n  fun ref getField2(): Set[String]\r\n  fun ref addString(str: String) =>\r\n    //Do Stuff\r\n    getField2().set(str)\r\n  fun ref removeString(str: String) =>\r\n    //Do Stuff\r\n    getField2().unset(str)\r\n  fun ref setStringSet(newSet: Set[String])\r\n\r\nclass Impl is Foo\r\n  let myfield1: Set[U32] = Set[U32].create()\r\n  fun ref _getField1(): Set[U32] =>\r\n    myfield1\r\n\r\nclass Impl2 is (Foo & Bar)\r\n  let myField1: Set[U32] = Set[U32].create()\r\n  var myField2: Set[String] = Set[String].create()\r\n\r\n  fun ref _getField1(): Set[U32] =>\r\n    myField1\r\n  fun ref getField2(): Set[String] =>\r\n    myField2\r\n  fun ref setStringSet(newSet: Set[String]) =>\r\n    myField2 = newSet\r\n```\r\n\r\nApologies if the capability typing is off or not ideal - I'm still getting used to it.\r\nThoughts?"},"comment":{"url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/comments/135292252","html_url":"https://github.com/CausalityLtd/ponyc/issues/282#issuecomment-135292252","issue_url":"https://api.github.com/repos/CausalityLtd/ponyc/issues/282","id":135292252,"user":{"login":"jemc","id":4623870,"avatar_url":"https://avatars.githubusercontent.com/u/4623870?v=3","gravatar_id":"","url":"https://api.github.com/users/jemc","html_url":"https://github.com/jemc","followers_url":"https://api.github.com/users/jemc/followers","following_url":"https://api.github.com/users/jemc/following{/other_user}","gists_url":"https://api.github.com/users/jemc/gists{/gist_id}","starred_url":"https://api.github.com/users/jemc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jemc/subscriptions","organizations_url":"https://api.github.com/users/jemc/orgs","repos_url":"https://api.github.com/users/jemc/repos","events_url":"https://api.github.com/users/jemc/events{/privacy}","received_events_url":"https://api.github.com/users/jemc/received_events","type":"User","site_admin":false},"created_at":"2015-08-27T04:56:10Z","updated_at":"2015-08-27T04:56:10Z","body":"I don't think I can make an argument good enough to overcome those obstacles :smiley:.\r\n\r\nBut conceptually, public fields are part of the public interface of a type, so it makes sense to be able to make `interface`s that reflect that.  As you mentioned, there are implementation reasons why this isn't very feasible, but I think the point is still valid.\r\n\r\nAs you alluded to near the end of your comment, defining accessors can be rather cumbersome.  Also, it somewhat defeats the purpose of a public field if you have to define public accessor methods to be able to use an `interface` with it.  Furthermore, because fields and methods share the same identifier-space, you can't use the public field's name for the method, so you have to name the method something like `get_foo()` instead of just `foo`.\r\n\r\nLike I said, I don't think these arguments are enough to overcome the implementation challenges, but I think they are worth noting."}}