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

Improving vocabulary module #67

Merged
merged 16 commits into from
Mar 18, 2024

Conversation

filippodebortoli
Copy link
Collaborator

@filippodebortoli filippodebortoli commented Mar 1, 2024

Addresses #60 and solves all the issues mentioned there, plus additional refactoring or renaming of some methods. Originally was #61, but having messed up with the git history there, I created a fresh branch and cherry-picked the right commits on top of devel.

It could already be merged. What do you think @althonos @phillord ?

@filippodebortoli filippodebortoli added the bug Something isn't working label Mar 1, 2024
@filippodebortoli filippodebortoli linked an issue Mar 1, 2024 that may be closed by this pull request
9 tasks
@filippodebortoli filippodebortoli added the enhancement New feature or request label Mar 1, 2024
@althonos
Copy link
Collaborator

althonos commented Mar 1, 2024

Since your vocab IRIs are all hardcoded somehow, you could implement Borrow<str> for them, and then you could do:

r.build.class(OWL::Thing).into()

which I think from an API perspective is nicer than having to call as_iri_str or as_iri_bytes!

@althonos
Copy link
Collaborator

althonos commented Mar 1, 2024

And as another remark I wonder if the WithIRI trait is really necessary, or if you couldn't just instead implement Deref<Target = Iri<String>> for the different namespace types. This way you don't need to implement the as_iri_str or as_iri_bytes yourself.

* Adds Deref<Target = IRI<String>>
* Adds TryFrom<&str> and TryFrom<&[u8]> (a lot of boilerplate).
* Deprecates most methods in WithIRI trait.
* Renames few methods in vocab to reflect their purpose.
* Moves model::Facet to vocab::Facet
@filippodebortoli
Copy link
Collaborator Author

Since your vocab IRIs are all hardcoded somehow, you could implement Borrow<str> for them, and then you could do:

r.build.class(OWL::Thing).into()

which I think from an API perspective is nicer than having to call as_iri_str or as_iri_bytes!

For now I implemented Borrow<str> only for the OWL enumeration, but it could be a good idea to do that for the other pieces of terminology eventually.

@filippodebortoli
Copy link
Collaborator Author

And as another remark I wonder if the WithIRI trait is really necessary, or if you couldn't just instead implement Deref<Target = Iri<String>> for the different namespace types. This way you don't need to implement the as_iri_str or as_iri_bytes yourself.

Agreed. I almost entirely could replace the behavior of WithIRI with standard traits such as Deref and TryFrom, there is only one method that is still troublesome which is io::rdf::reader::vocab_lookup where I could not find a way to replace the call to as_iri_str(). Do you have any suggestion?

@althonos
Copy link
Collaborator

althonos commented Mar 1, 2024

Agreed. I almost entirely could replace the behavior of WithIRI with standard traits such as Deref and TryFrom, there is only one method that is still troublesome which is io::rdf::reader::vocab_lookup where I could not find a way to replace the call to as_iri_str(). Do you have any suggestion?

The issue is with Deref not giving access to the reference lifetime, so you cannot return a HashMap<&'static str, _> here because the compiler cannot know the reference is static. However, since vocab_lookup is only ever called once when launching a parser, I think vocab_lookup could be made to return a HashMap<String, _> without any actual performance penalty there.

@filippodebortoli
Copy link
Collaborator Author

Agreed. I almost entirely could replace the behavior of WithIRI with standard traits such as Deref and TryFrom, there is only one method that is still troublesome which is io::rdf::reader::vocab_lookup where I could not find a way to replace the call to as_iri_str(). Do you have any suggestion?

The issue is with Deref not giving access to the reference lifetime, so you cannot return a HashMap<&'static str, _> here because the compiler cannot know the reference is static. However, since vocab_lookup is only ever called once when launching a parser, I think vocab_lookup could be made to return a HashMap<String, _> without any actual performance penalty there.

I tried to go for that.
With this, vocab::WithIRI could be deprecated.
The only "issue" is that now we have a lot of duplicated code for each enumeration in vocab.
One solution could be to write a macro that generates the implementations of Deref, TryFrom and Borrow for each such enumeration.

src/vocab.rs Outdated
@@ -83,13 +137,53 @@ pub enum RDF {
Type,
}

impl TryFrom<&str> for RDF {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you should just delegate to the TryFrom<[u8]> implementation here:

impl TryFrom<&str> for Namespace {
    type Error = HornedError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        Self::try_from(value.as_bytes())
    }
}

And also you could implement FromStr if you're gonna implement TryFrom<&str>.

@althonos
Copy link
Collaborator

althonos commented Mar 3, 2024

I think this could be all wrapped in a macro that takes care of both the lazy_meta and of the associated trait implementation indeed.

…ve macros.

* Substantial refactoring of vocab.rs.
* Now, strings associated to variants are generated by vocabulary_type.
* lazy_meta! is called from vocabulary_type.
* vocab::is_thing and vocab::is_nothing moved to model::Class.
* tests to check behaviour of new macros added.
@filippodebortoli
Copy link
Collaborator Author

I think this could be all wrapped in a macro that takes care of both the lazy_meta and of the associated trait implementation indeed.

Done, see vocab::vocabulary_type and vocab::vocabulary_traits.

vocabulary_traits! generates the code implementing FromStr, TryFrom<str>, TryFrom<[u8]> and Deref for each vocabulary type.
vocabulary_type! generates the enumeration associated to a type of vocabulary, produces the IRIs corresponding to each variants by prepending the appropriate namespace and having a flag telling if the name of the variant should be used as-is for the IRI generation or if the first letter should be transformed to lowercase.

@filippodebortoli filippodebortoli marked this pull request as draft March 5, 2024 09:32
@phillord
Copy link
Owner

phillord commented Mar 5, 2024

I think that this looks good. The complexity of macros added in vocab.rs is more than made up for by the regularity and use of standard traits in the rest of the code.

Do we need to deprecate WithIRI? Or do we just delete it?

@althonos
Copy link
Collaborator

althonos commented Mar 5, 2024

You're in 0.* so you could just delete it, that's fine according to semver 👍

@althonos
Copy link
Collaborator

althonos commented Mar 5, 2024

By the way I am compiling a list of things to improve regarding Rust conventions (capitalization in some identifiers is not standard, some methods could be renamed to a more standard name like as_x or to_y to convey intent) and traits (e.g. MutableOntology can defer some of the work to the Extend standard trait), I'll create an issue dedicated to that and I'll will likely be very full of API breaks.

@filippodebortoli filippodebortoli marked this pull request as ready for review March 6, 2024 12:27
@filippodebortoli
Copy link
Collaborator Author

You're in 0.* so you could just delete it, that's fine according to semver 👍

Alright, I updated the code to remove all that was deprecated.
I think the PR is ready for merge after review.

@filippodebortoli filippodebortoli assigned phillord and unassigned phillord Mar 6, 2024
@phillord
Copy link
Owner

phillord commented Mar 7, 2024

Added one minor review issue. I also wonder about the tests -- they are getting fairly long now, and I wonder whether we should use a "test" module at the end. The reason I worry is that tests tend to churn more rapidly than "real" code and that can make the diffs harder to read. WDYT?

@filippodebortoli
Copy link
Collaborator Author

Added one minor review issue. I also wonder about the tests -- they are getting fairly long now, and I wonder whether we should use a "test" module at the end. The reason I worry is that tests tend to churn more rapidly than "real" code and that can make the diffs harder to read. WDYT?

Addressed in commit de6161e. I could not see the review issue here on GitHub, what is it about?

@filippodebortoli
Copy link
Collaborator Author

If there is no objection or further improvement in this direction I would merge this onto devel.

@phillord
Copy link
Owner

Good for me

@filippodebortoli filippodebortoli merged commit d88964b into phillord:devel Mar 18, 2024
1 check passed
@filippodebortoli filippodebortoli deleted the fixes/vocabulary branch March 18, 2024 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactoring vocab module and fix potentially broken methods.
3 participants