{"action":"created","issue":{"url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/4","labels_url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/4/labels{/name}","comments_url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/4/comments","events_url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/4/events","html_url":"https://github.com/bluss/petulant-avenger-graphlibrary/issues/4","id":85554188,"number":4,"title":"Some thoughts and ideas related to Graph.","user":{"login":"mitchmindtree","id":4587373,"avatar_url":"https://avatars.githubusercontent.com/u/4587373?v=3","gravatar_id":"","url":"https://api.github.com/users/mitchmindtree","html_url":"https://github.com/mitchmindtree","followers_url":"https://api.github.com/users/mitchmindtree/followers","following_url":"https://api.github.com/users/mitchmindtree/following{/other_user}","gists_url":"https://api.github.com/users/mitchmindtree/gists{/gist_id}","starred_url":"https://api.github.com/users/mitchmindtree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitchmindtree/subscriptions","organizations_url":"https://api.github.com/users/mitchmindtree/orgs","repos_url":"https://api.github.com/users/mitchmindtree/repos","events_url":"https://api.github.com/users/mitchmindtree/events{/privacy}","received_events_url":"https://api.github.com/users/mitchmindtree/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":13,"created_at":"2015-06-05T15:05:53Z","updated_at":"2015-06-09T11:15:57Z","closed_at":"2015-06-09T05:43:40Z","body":"During my use of `Graph` in dsp-chain I've run into a few issues for which there don't yet seem to be any easy work-arounds and often I find myself resorting to unsafe code when there is probably a nicer solution possible within `Graph`'s API. Most instances revolve around gaining simultaneous mutable access to multiple different nodes/edges at once. Just thought I'd share some of these issues along with some thoughts and ideas on how they might be addressed.\r\n\r\nAccess to incoming edges\r\n-----------------------------------\r\n\r\nI've noticed that Graph provides two main methods for iterating over edges of a given node:\r\n\r\n- `edges`: provides an iterator over the outgoing edges paired with their respective node indices.\r\n- `edges_both`: provides an iterator over all edges paired with their respective node indices.\r\n\r\nHere are some thoughts that came to mind:\r\n- Perhaps `edges` could take a `Direction` argument so that a user may iterate over either direction, rather than only `Outgoing`?\r\n- Perhaps it would be useful to provide `edges_mut` and `edges_both_mut` variations?\r\n- Maybe `edges_undirected` (instead of `edges_both`) would be more consistent with `neighbors_undirected` and `find_edge_undirected`?\r\n\r\nSimultaneous mutable access to a node and its edges.\r\n-------------------------------------------------------------------------\r\n\r\nThere are a few variations on this problem, the two that I've run into are:\r\n\r\n- Needing both mutable access to a node weight and immutable access to its incoming edge weights simultaneously.\r\n- Needing both immutable access to a node weight and mutable access to its outgoing edge weights simultaneously.\r\n\r\nThe exact use case within dsp-chain is: (during a reverse dfs) each node must be able to read from each of its incoming edge's buffers so that it may sum them to its own buffer. Once it has rendered its own buffer, it then writes the result to each of its outgoing edges' buffers. This must all be achieved without allocating any new intermediate buffers.\r\n\r\nIn the API's current state I'm unsure of how to get around this without unsafe code. I imagine it should be possible to expose a safe interface to this use-case so that the above examples look something like:\r\n\r\n```Rust\r\n// Mutable access to a node weight and immutable access to its incoming edge weights simultaneously.\r\ngraph.node_mut_with_edges(node_idx, pg::Incoming, |node_weight_mut, edge_weights| {\r\n    for edge_weight in edge_weights {\r\n        // do stuff with node_weight_mut and edge_weight....\r\n    }\r\n})\r\n\r\n// Immutable access to a node weight and mutable access to its outgoing edge weights simultaneously.\r\ngraph.node_with_edges_mut(node_idx, pg::Outgoing, |node_weight, edge_weights_mut| {\r\n    for edge_weight_mut in edge_weights_mut {\r\n        // do stuff with node_weight and edge_weight_mut...\r\n    }\r\n});\r\n```\r\n\r\nPair indexing\r\n-----------------\r\n\r\nIt would be nice to be able to index into the graph twice at once, i.e. perhaps by allowing indexing the `Graph` with tuples.\r\n\r\n```Rust\r\nlet (a_weight, b_weight) = &mut graph[(a, b)];\r\n```\r\n\r\nI noticed that you have a private `index_twice` function in the graph module already - perhaps there's a reason you've avoided exposing it? I guess one problem with this is that the returned references are always either 1. both immutable or 2. both mutable, without exposing an option for combinations of the two.\r\n\r\n\r\nAnyway, apologies for the lengthy issue! These are currently things I'm dodging with unsafe, but just thought I'd come to the source, share my experience and perhaps land a nicer solution closer to home - let me know your thoughts when you get a chance :) Also, if there are already nice solutions to any of the above that I might have missed, please feel free to share!"},"comment":{"url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/comments/110320943","html_url":"https://github.com/bluss/petulant-avenger-graphlibrary/issues/4#issuecomment-110320943","issue_url":"https://api.github.com/repos/bluss/petulant-avenger-graphlibrary/issues/4","id":110320943,"user":{"login":"mitchmindtree","id":4587373,"avatar_url":"https://avatars.githubusercontent.com/u/4587373?v=3","gravatar_id":"","url":"https://api.github.com/users/mitchmindtree","html_url":"https://github.com/mitchmindtree","followers_url":"https://api.github.com/users/mitchmindtree/followers","following_url":"https://api.github.com/users/mitchmindtree/following{/other_user}","gists_url":"https://api.github.com/users/mitchmindtree/gists{/gist_id}","starred_url":"https://api.github.com/users/mitchmindtree/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mitchmindtree/subscriptions","organizations_url":"https://api.github.com/users/mitchmindtree/orgs","repos_url":"https://api.github.com/users/mitchmindtree/repos","events_url":"https://api.github.com/users/mitchmindtree/events{/privacy}","received_events_url":"https://api.github.com/users/mitchmindtree/received_events","type":"User","site_admin":false},"created_at":"2015-06-09T11:15:57Z","updated_at":"2015-06-09T11:15:57Z","body":"Just [made the changes](https://github.com/RustAudio/dsp-chain/pull/116/files) and she seems to be working beautifully! Also quite a bit neater :) Once again, many thanks!"}}