Hacker News new | ask | show | jobs
by DemocracyFTW2 691 days ago
I stumbled over

    use jiff::{Timestamp, ToSpan};

    fn main() -> Result<(), jiff::Error> {
        let time: Timestamp = "2024-07-11T01:14:00Z".parse()?;
I seem to remember Rust does that thing with interfaces instead of classes, is it that? How come I import a library and all of a sudden strings have a `parse()` method that despite its generic name results in a `Timestamp` object? or is it the left-hand side that determines which meaning `str.parse()` should have? What if I have two libraries, one for dates and one for say, Lisp expressions that both augment strings with a `parse()` method? Why use this syntax at all, why not, say, `Timestamp.parse( str )`? I have so many questions.
6 comments

`parse` is actually an inherent method on `str` that always exists: https://doc.rust-lang.org/core/primitive.str.html#method.par...

Its return type is generic, and here it's inferred from the left hand side. It's implemented using the `FromStr` trait, and you can equivalently write `Timestamp::from_str(t)`.

You're thinking of the "extension trait" pattern for using traits to add methods to existing types when the trait in scope, but that's not what's going on here. Jiff's `ToSpan` mentioned above is an example of that pattern, though: https://docs.rs/jiff/latest/jiff/trait.ToSpan.html

All of these options work and are equivalent.

- let time = Timestamp::parse("2024-07-11T01:14:00Z")?;

- let time: Timestamp = "2024-07-11T01:14:00Z".parse()?;

- let time = "2024-07-11T01:14:00Z".parse::<Timestamp>()?;

You’re free to choose whatever you prefer, although the compiler needs to be able to infer the type of time. If it can’t, it’ll let you know.

So a fourth option is allowed, as long as the subsequent lines make the type of time unambiguous.

- let time = "2024-07-11T01:14:00Z".parse()?;

This is a direct consequence of Timestamp implementing the FromStr trait.

  let time = Timestamp::from_str("2024-07-11T01:14:00Z")?;
I think you meant :)
Haha, yes I did. If only the HN textbox integrated with rust-analyzer, it would have caught the mistake.
It’s because Timestamp implements the FromStr trait which is one of the first traits everyone learns about when learning rust. So when you say that your value is a Timestamp and the expression is string.parse()?, the compiler knows that it has to use the implementation which returns a Timestamp.

There will never be two libraries that clash because of Rust’s orphan rule: you can only implement either a trait which you define on any type, or define a foreign trait on a type which you define, so there’s no way for some random library to also ship an implementation of FromStr for Timestamp

Although I sure wish sometimes I could just do that my own binary/non-lib projects
Rust will determine what `parse` does based on the inferred return type (which is being explicitly set to `Timestamp` here). This is possible when the return type has `FromStr` trait.
oh I see, almost what I anticipated
> I have so many questions.

Not being snarky, but I suggest starting by reading at least a little about traits? None of your questions are really about this library - it's just FromStr and an orphan rule.

To make it clear, I didn't want to be the snark either. Just wondered about the usual things like "locally detectable semantics" and so on. I still think `Library.method( argument )` wins over `argument.method()` for the simple reason that the former has `Library` explicitly mentioned. Also, `door.open()`, really? I think `strongman.open( door )` is just that much clearer, flexible and explicit.
Agree to disagree. I always like expressiveness of Ruby, so `2.days` and `2.days()` look totally normal to me.

> `strongman.open( door )` is just that much clearer, flexible and explicit.

Where the strongman came from? Entirely different semantics.

It's implied. Here is the full syntax.

> let time: Timestamp = "2024-07-11T01:14:00Z".parse::<Timestamp>()?;

That ::<TYPE> thing at the end is called a turbofish. It is rarely necessary to give it explicitly (but sometimes you do when the compiler cannot infer the return type on its own—thusfar in my own rust coding I’ve needed it exactly once).
It’s useful to know the full syntax, I’ve definitely encountered needing it more than one time.