{"action":"created","issue":{"url":"https://api.github.com/repos/manastech/crystal/issues/1517","labels_url":"https://api.github.com/repos/manastech/crystal/issues/1517/labels{/name}","comments_url":"https://api.github.com/repos/manastech/crystal/issues/1517/comments","events_url":"https://api.github.com/repos/manastech/crystal/issues/1517/events","html_url":"https://github.com/manastech/crystal/issues/1517","id":107162133,"number":1517,"title":"[RFC] Separating pass by value from memory allocation location","user":{"login":"technorama","id":51043,"avatar_url":"https://avatars.githubusercontent.com/u/51043?v=3","gravatar_id":"","url":"https://api.github.com/users/technorama","html_url":"https://github.com/technorama","followers_url":"https://api.github.com/users/technorama/followers","following_url":"https://api.github.com/users/technorama/following{/other_user}","gists_url":"https://api.github.com/users/technorama/gists{/gist_id}","starred_url":"https://api.github.com/users/technorama/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/technorama/subscriptions","organizations_url":"https://api.github.com/users/technorama/orgs","repos_url":"https://api.github.com/users/technorama/repos","events_url":"https://api.github.com/users/technorama/events{/privacy}","received_events_url":"https://api.github.com/users/technorama/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/manastech/crystal/labels/compiler","name":"compiler","color":"fef2c0"},{"url":"https://api.github.com/repos/manastech/crystal/labels/draft","name":"draft","color":"00B8B8"},{"url":"https://api.github.com/repos/manastech/crystal/labels/RFC","name":"RFC","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":4,"created_at":"2015-09-18T09:10:47Z","updated_at":"2015-09-23T18:02:22Z","closed_at":null,"body":"Currently objects are reference (heap) allocated with pass by reference semantics.  Structs are inline allocated on the stack or as part of another object with pass by value semantics.  The behavior of pass by X or allocate in location Y are not inherently tied together.\r\n\r\nPassing by x defines the semantics by which the program is structured.\r\nAllocating on the stack or heap is an optimization and shouldn't effect how the program is structured.\r\n\r\nMixing these 2 concepts forces users to restructure their programs when optimizing or forgo optimizing to gain the desired passing behavior.\r\n\r\nA better model would allow specific Objects to be optionally allocated locally through annotation, keyword or some other method.  \r\n\r\n. | Pass by Ref | Allocate Heap | Pass by Val | Allocate Local\r\n--- | --- | --- | --- | ---\r\nObject(heap) | :white_check_mark: | :white_check_mark: | |\r\nObject(local) | :white_check_mark: | | | :white_check_mark: \r\nStruct |  | | :white_check_mark:  | :white_check_mark:\r\n\r\nThe current state of crystal\r\n\r\n. | Pass by Ref | Allocate Heap | Pass by Val | Allocate Local\r\n--- | --- | --- | --- | ---\r\nObject | :white_check_mark: | :white_check_mark: | |\r\nStruct |  | | :white_check_mark:  | :white_check_mark:\r\n\r\n\r\nSome use cases\r\n* No need to change from class to struct just to change the memory location and risk breaking existing code.\r\n*  Video game programming with object pooling.  Pass by reference is desired but iteration over the entire collection is common (memory locality).\r\n* Memory locality for inline objects that retain pass by reference semantics when the inner objects are passed to other functions.\r\n"},"comment":{"url":"https://api.github.com/repos/manastech/crystal/issues/comments/142681318","html_url":"https://github.com/manastech/crystal/issues/1517#issuecomment-142681318","issue_url":"https://api.github.com/repos/manastech/crystal/issues/1517","id":142681318,"user":{"login":"ozra","id":563674,"avatar_url":"https://avatars.githubusercontent.com/u/563674?v=3","gravatar_id":"","url":"https://api.github.com/users/ozra","html_url":"https://github.com/ozra","followers_url":"https://api.github.com/users/ozra/followers","following_url":"https://api.github.com/users/ozra/following{/other_user}","gists_url":"https://api.github.com/users/ozra/gists{/gist_id}","starred_url":"https://api.github.com/users/ozra/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ozra/subscriptions","organizations_url":"https://api.github.com/users/ozra/orgs","repos_url":"https://api.github.com/users/ozra/repos","events_url":"https://api.github.com/users/ozra/events{/privacy}","received_events_url":"https://api.github.com/users/ozra/received_events","type":"User","site_admin":false},"created_at":"2015-09-23T18:02:22Z","updated_at":"2015-09-23T18:02:22Z","body":"At risk of repeating something I've already written somewhere else in the issues mountain:\r\n\r\nI agree for some change regarding this, I hope the following is understandable, a bit tired atm:\r\n\r\nDeclarings structure (class) and allocation mode should be separated.\r\n\r\n- If I create an array of objects, I probably don't want it to be an array of references.\r\n- If I create a class containing members of other classes, I may want them to be references, or, just as likely \"inlined\" (memory locality), as structs are.\r\n- If I pass an object to a function (method) I might very well want it to be by reference, (but might want it immutable - other issue), even though it might be allocated \"in\" another object (composed class), or in an array.\r\n- If I create an object in a method, locally assigned, it might very well be better off on the stack (escape analysis for this case).\r\n\r\n`Objects` should be `classes`, and that's it, for the allocation behaviour, it seems to me, some hinting keyword like `val` and `ref` could be of use, both for data-members in class-defs and method param-defs.\r\n\r\nThis of course means that code like `@some–val–member = SomeType.new()` must fail (returns ref), the initializer should be used on the already 'part-of-this-allocated' object.\r\n"}}