Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remote Feature #120

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

astrale-sharp
Copy link
Collaborator

Hi!!

I refactored the code around a macro and operation on the map.

This works and pass all the test and is more expressive but more complex (this was one of my first macro : a pain) although some of the new code could be improved, I'm also unsure about the naming.

If you're interested in giving me a review you're more than welcome !
@arnaudgolfouse @MatejSloboda

@astrale-sharp
Copy link
Collaborator Author

Also note that you cannot undo a remove connection yet, it should be easy to implement.

@astrale-sharp
Copy link
Collaborator Author

Also note that
Documentation/Comments surrounding this PR could be improved

The method generated by the macro return a Result, the impl to return this result is correct but stupid, I doubt the use for Errors is really useful and this probably could be improved as well, open to suggestions.

operation enum, undo feature

new defaults with function signature like impl Into<Parameter>

add DijkstraMap::get_connection
@arnaudgolfouse
Copy link
Contributor

The more I look at it, the more I wonder if the macro enum_operation is truly necessary. Could we not just use DijkstraMap::apply_operation everywhere ?

Maybe then you'll say that it will be hard keeping Remote and DijkstraMap in sync, but consider this : if we only use apply_operation, we only need one method on Remote:

impl Remote {
    pub fn apply_operation(&mut self, operation: Operation) { // bikeshiddable name, of course
        self.operations.push(operation);
    }
}

@arnaudgolfouse
Copy link
Contributor

arnaudgolfouse commented Mar 22, 2023

Btw, there are some clippy-related warnings still fired by the crate in this state.

}
}

impl Into<Directional> for Option<bool> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think those impl should not exist : they are fully redundant with .unwrap_or_default(), and I honestly had a hard time parsing some pieces of code.
For example, some code reads

self
    .connect_points(*source, *target, Some(*weight), false))
    .and(self.connect_points(*target, *source, Some(*weight), Some(false)))

why does the first call use false, and the second Some(false) ?

#[fn = set_terrain_for_point; err = PointNotFound;]
SetTerrainForPoint {
id: PointId,
ttype: TerrainType,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

come on, we can't write terrain_type ? 😛

match self {
Operation::AddPoint { id, terrain_type: _ } => Self::RemovePoint { id: *id },
Operation::AddPointReplace { id, terrain_type : _ } => {
if map.has_point(*id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that, when the point is already present, the semantics of AddPointReplace are "RemovePoint followed by AddPoint", right ?

But then, we can't actually reverse this, for the same reason we can't reverse RemovePoint!

if matches!(*directional, Directional::Bidirectional) {
match self
.connect_points(*source, *target, Some(*weight), false)
.and(self.connect_points(*target, *source, Some(*weight), Some(false)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

connect_points calls apply_operation again and ends up in this same match arm, and I find these hoops a bit difficult to follow...

I propose doing this instead (effectively inlining those connect_points calls), how does that look to you ?

// target -> source
let (connections, reverse_connections) = self
    .get_connections_and_reverse(*source, *target)
    .map_err(|_| Errors::PointNotFound(PointNotFound))?;
connections.insert(*target, *weight);
reverse_connections.insert(*source, *weight);
if *directional == Directional::Bidirectional {
    // source -> target
    let (connections, reverse_connections) = self
        .get_connections_and_reverse(*target, *source)
        .map_err(|_| Errors::PointNotFound(PointNotFound))?;
    connections.insert(*source, *weight);
    reverse_connections.insert(*target, *weight);
}
Ok(None)

Copy link
Contributor

@arnaudgolfouse arnaudgolfouse Mar 28, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see how the duplication is not ideal though... Maybe with a closure ?

if matches!(*directional, Directional::Bidirectional) {
if self
.remove_connection(*source, *target, false)
.and(self.remove_connection(*target, *source, false))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as ConnectPoints

directional,
} => {
// let bidirectional = bidirectional.unwrap_or(true);
// let weight = weight.unwrap_or(Weight(1.0));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be removed ?

// let weight = weight.unwrap_or_default();
// let directional = directional.unwrap_or_default();
// self.operations.push(Operation::ConnectPoints {
// source,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove these comments ?

}
}

impl Into<Directional> for bool {
Copy link
Contributor

@arnaudgolfouse arnaudgolfouse Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh I just noticed !
Did you know that bool::default() is false ?
This mean that with both of these impl there, we have

let directional_1: Directional = Directional::default();
let directional_2: Directional = bool::default().into();
assert!(directional_1 != directional_2);

This seems like a problem...

@arnaudgolfouse
Copy link
Contributor

As we discussed, I put an alternative design here : https://github.com/arnaudgolfouse/Dijkstra_map_for_Godot/tree/alternative-operation-design
Feel free to take whatever interests you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants