{"action":"created","issue":{"url":"https://api.github.com/repos/TyOverby/ares/issues/34","labels_url":"https://api.github.com/repos/TyOverby/ares/issues/34/labels{/name}","comments_url":"https://api.github.com/repos/TyOverby/ares/issues/34/comments","events_url":"https://api.github.com/repos/TyOverby/ares/issues/34/events","html_url":"https://github.com/TyOverby/ares/issues/34","id":110829000,"number":34,"title":"Prototypal inheritance","user":{"login":"TyOverby","id":573215,"avatar_url":"https://avatars.githubusercontent.com/u/573215?v=3","gravatar_id":"","url":"https://api.github.com/users/TyOverby","html_url":"https://github.com/TyOverby","followers_url":"https://api.github.com/users/TyOverby/followers","following_url":"https://api.github.com/users/TyOverby/following{/other_user}","gists_url":"https://api.github.com/users/TyOverby/gists{/gist_id}","starred_url":"https://api.github.com/users/TyOverby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TyOverby/subscriptions","organizations_url":"https://api.github.com/users/TyOverby/orgs","repos_url":"https://api.github.com/users/TyOverby/repos","events_url":"https://api.github.com/users/TyOverby/events{/privacy}","received_events_url":"https://api.github.com/users/TyOverby/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-10-11T02:24:22Z","updated_at":"2015-10-11T02:45:17Z","closed_at":null,"body":"This is obviously a contentious feature to add to any langauge (especially a lisp), but I think that prototypal inheritance is a good way to add code reuse and \"inheritance\" while not adding complications to the language.  \r\n\r\n## Method Syntax\r\nRight now there is only one way to call a function on some data.\r\n```clojure\r\n(move-player player x y)\r\n```\r\n\r\nBut instead of polluting the global namespace, and in order to more closely relate objects and their properties, it would be nice to write this:\r\n```clojure\r\n(player.move x y)\r\n```\r\n\r\nThe lambda for `move-player` and `player.move` could be identical\r\n```clojure\r\n(lambda (player x y)\r\n    (setm player 'x x) ; hypothetical hashmap set function \r\n    (setm player 'y y)\r\n    player)\r\n```\r\nbut when called in the \"method notation\" (`player.move`), it would automatically place the `player` in the first argument slot.\r\n\r\nThis would only happen for Maps that have Symbols mapping to functions.  \r\n\r\n## Fallback (optional)\r\nThis is an optional addition to method notation.\r\nWhen the receiver of a method call either _isn't_ a map, or can't be found in the map, a function is looked for in the current environment and used instead.\r\n```clojure\r\n(my-list.map (lambda (x) (* x x)))\r\n```\r\n\r\n## Field Syntax\r\nSame as method syntax, but for fields.\r\n```\r\n(print game-object.x) \r\n```\r\nThis might need to be different from method syntax, but it could be possible to join them together (so that `(foo.bar x y z)` is just doing a field access on `foo.bar` and calling it.\r\n\r\n## Prototypes\r\nWhen a method is called on a map that does not contain the method name, the next place to look is in the object under `'prototype`.  If the method is found there, it is called with the outermost object as the first argument (the explicit \"this\").  If not, that object's prototype is checked, and so on and so forth.\r\n\r\n## Prototype keyword generator (optional)\r\nInstead of using just `'prototype` for accessing the prototype object, we should probably have a single unique symbol generated at runtime and used to set the prototype object.\r\n\r\nAn example implementation\r\n```clojure\r\n(define prototype ((lambda () \r\n    (define proto (gensym))\r\n    (lambda () proto))))\r\n\r\n(define myobj {\r\n    'x 1 \r\n    (prototype) { \r\n        'f (lambda (this) (set this.x 5)) })\r\n\r\n(print myobj.x) ; 1\r\n(myobj.f)\r\n(print myobj.x) ; 5\r\n```"},"comment":{"url":"https://api.github.com/repos/TyOverby/ares/issues/comments/147149085","html_url":"https://github.com/TyOverby/ares/issues/34#issuecomment-147149085","issue_url":"https://api.github.com/repos/TyOverby/ares/issues/34","id":147149085,"user":{"login":"TyOverby","id":573215,"avatar_url":"https://avatars.githubusercontent.com/u/573215?v=3","gravatar_id":"","url":"https://api.github.com/users/TyOverby","html_url":"https://github.com/TyOverby","followers_url":"https://api.github.com/users/TyOverby/followers","following_url":"https://api.github.com/users/TyOverby/following{/other_user}","gists_url":"https://api.github.com/users/TyOverby/gists{/gist_id}","starred_url":"https://api.github.com/users/TyOverby/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/TyOverby/subscriptions","organizations_url":"https://api.github.com/users/TyOverby/orgs","repos_url":"https://api.github.com/users/TyOverby/repos","events_url":"https://api.github.com/users/TyOverby/events{/privacy}","received_events_url":"https://api.github.com/users/TyOverby/received_events","type":"User","site_admin":false},"created_at":"2015-10-11T02:45:17Z","updated_at":"2015-10-11T02:45:17Z","body":"If we adopted method syntax (even without prototypal inheritance) it would make things like extending \"map\" possible.\r\n\r\n```clojure\r\n(define map (lambda (obj f) \r\n    (switch obj\r\n        list? (map-list obj f)\r\n        option? (map-option obj f)\r\n        truthy? (obj.map f))))\r\n```\r\n\r\nHowever, if we wanted to use this pattern, we couldn't have fallback, because then the above could infinitely recurse if obj doesn't have a `'map` method on it.\r\n\r\nMaybe a `contains-nested?` function that could be used to guard against the infinite recursion?"}}