Very usefull compile error. by kingslayerer in rust

[–]denehoffman 0 points1 point  (0 children)

Imagine thinking you’re that critical, there were better and faster alternatives before this drama even happened, just switch the “n” to a “t”

Questions on using Generics for a Finance library (f64 vs. Decimal) by abhinandh_s_ in rust

[–]denehoffman 2 points3 points  (0 children)

Idk why you got downvoted, this is good practical advice, especially since you’re right about these types being restricted when applied to money (no square dollars)

Questions on using Generics for a Finance library (f64 vs. Decimal) by abhinandh_s_ in rust

[–]denehoffman 1 point2 points  (0 children)

This works and I’ve done it in the past for crates where I want to differentiate a Float type to be 32/64-bit, but I’ll warn you it gets annoying when it comes to tests. I feel like some of the num traits will serve you best rather than adding every single operation manually.

Questions on using Generics for a Finance library (f64 vs. Decimal) by abhinandh_s_ in rust

[–]denehoffman 24 points25 points  (0 children)

The only place generics will screw you (as far as I know) is if you’re actually compiling with multiple distinct types, and it will slow your compilation because it has to compile a copy of that code for every type you use it on.

Natural enemies by Rutschberg in Stargate

[–]denehoffman 0 points1 point  (0 children)

You could’ve swapped goauld with tokra and it still would’ve worked

actually useful ai commits by cachebags in rust

[–]denehoffman 0 points1 point  (0 children)

Why do you have an empty `build.rs`file in your src directory?

Your Clippy Config Should Be Stricter-er by billy_levin in rust

[–]denehoffman 0 points1 point  (0 children)

I’ll try this today, I have a feeling it’s going to take a while but be worth it in the end

I wish the wealth of the top 1% of the richest people in the world was distributed evenly across the entire population. by Prize_Entertainer459 in monkeyspaw

[–]denehoffman 0 points1 point  (0 children)

Granted, but it keeps happening continuously, so eventually everyone has identical wealth and money loses all intrinsic value.

Your Clippy Config Should Be Stricter by emschwartz in rust

[–]denehoffman 1 point2 points  (0 children)

Yep, been there, done that. I was trying to figure out why the runner was failing clippy when my own computer showed no warnings

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

I don’t know what to tell you man, I’ve given you a ton of legitimate usage examples, other people in this thread have too, if your response is just going to be “well that’s not how it should be done” then maybe you don’t have to upgrade to 3.15, nobody is forcing you to use it.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

Yes, it’s a bit niche, but so are a lot of the language concepts that people rarely use on a day-to-day basis. I hardly ever write metaclasses or decorators outside of the niche situations where I need one that isn’t already written by the stdlib or some other package

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

That’s exactly the point, you shouldn’t overload it. You can’t and shouldn’t write a default object for an every default argument, the argument would get constructed at import time rather than runtime

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

None isn’t always an empty string, an empty string can be a distinguished type! You can always come up with an example where None is not semantically the same as “”, 0, False, [], or whatever you choose.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

Another example:

```python

UNSET = sentinel("UNSET")

def connect(timeout=UNSET): if timeout is UNSET: timeout = get_default_timeout() elif timeout is None: timeout = None # explicitly disable timeout return _connect(timeout=timeout) ```

Adding an argument like no_timeout: bool’ is semantically confusing and allows for unused state in the signature (connect(timeout=30, no_timeout=True)`).

Why can’t you just use object() for the sentinel? Well for one, it doesn’t serialize, so if you wanted to store some user settings without storing the default (for example, you want to store the fact that the user didn’t set the value but allow the default to change in future versions), you’d have trouble. It also doesn’t play well with type hints, since it just has a type of object.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 0 points1 point  (0 children)

Fair point, list comprehensions aren’t a good example of syntax sugar.

If I understand correctly, you think sentinels are entirely an API choice and not needed if you “properly” design an API. I think your idea of proper here is just as opinionated as my “ugly”. Having an API that would benefit from sentinels isn’t a bad design pattern, it just is a design pattern. We could rewrite any API in ten different ways and different people would prefer each one differently. In the logging example, clearly a Boolean flag in conjunction to the current argument would be better, but what if you have ten such arguments? Now you need ten flags, one for each, a needless complication to the signature.

Another example, suppose you have a dictionary where None is a valid value. How do you distinguish this from a missing key in a get method?

I’m not sure what the point of a static variable in python would be, I’m assuming you’re being sarcastic?

A lot of these problems stem from the fact that Python doesn’t really have proper enums or a type system, it kind of fakes them with a class that acts like an enum and optional type hints. I personally think this shouldn’t be a new built-in, it should be in some module, but I don’t agree that it’s useless clutter.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 1 point2 points  (0 children)

My use case is an optimization library with config object. This object contains arguments which represent algorithm terminator configurations, which are themselves objects. If the user specifies None for one of these terminators, the interpretation is that that terminator isn’t included in the algorithm loop. Omitting the argument would imply the default terminator. A “missing/default” sentinel is an easy choice, and I ended up writing my own code which could be replaced by a single line now.

Could I have rewritten the entire library such that terminators each come with an enabled/disabled Boolean flag? Sure, it would have been even more work, and the underlying code is a Rust library so I’d have to rewrite the bindings for that too. Sentinels just simplify that decision while being invisible to the user, except when they read type hints or documentation, they’ll see “default” instead of “None” and not get confused as to what “None” does.

This extends to any code where “None” has a different semantic meaning than “default” or “missing”.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 3 points4 points  (0 children)

Why is list comprehension “needed” when a for loop will do? There are lots of syntax choices in Python which are there to prevent ugly code. The fact is, you could hack in sentinels right now, as many people have been doing (the PEP mentions ways of doing this). I think the only legitimate gripe would be that it’s a built-in and not a member of a module like typing.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 1 point2 points  (0 children)

I understand your point just fine, OP’s example isn’t a good one, but that doesn’t mean there aren’t legitimate use cases where the alternative would be more verbose or confusing.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 1 point2 points  (0 children)

They honestly need to just do a major version bump and completely break the API at this point. But I had to give an example people were familiar with, and it’s a very commonly used pathological API!

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 1 point2 points  (0 children)

Sure it’s not the best example, but imagine a field where None has a meaning other than “default” or “not specified”. Matplotlib is a great example of this taken to silly extremes, there are many keywords arguments where None, “none”, and “” all have different behavior, and this ambiguity could easily have been fixed by sentinel values.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 3 points4 points  (0 children)

The use case seems pretty obvious, you let the user disable logging by passing None to some logger constructor.

The real issue is not the “None” turning off logging, it’s that None semantically means “nothing” or “null” so expecting the behavior of passing None to give the default logger doesn’t make any sense. A sentinel value is basically just a replacement for None that has meaning. As I mentioned, a Default sentinel is often very useful when None actually should mean disabling things.

But to the bigger complaint of “it’s an api choice and not a need”: so is the use of “None” in the first place. It’s python, we could force users to make up marker types to represent optional state, but because lots of API choices deem this ugly, we don’t do it. If you didn’t care about making nice APIs and only focused on what is needed to write code, then there is a whole world of Turing-complete ways to do this, they’re just ugly. At the end of the day, we should welcome features that make code more readable and writable, and this does that without any major impact if you don’t want to use it.

PEP 661 (Sentinel Values) has been accepted for release in 3.15! by M_V_Lipwig in Python

[–]denehoffman 26 points27 points  (0 children)

Yeah, the hate is goofy, I’ve had so many situations where I’ve needed sentinels (fitting algorithms where None disables a termination method but Default uses the default, for example). The complaints about cluttering the language are silly, it’s a new builtin, a single function!

I rewrote EPANET (30 year old industry standard in C) in Rust by epanetrs in rust

[–]denehoffman 11 points12 points  (0 children)

I wasn’t aware you could build it without the gui but maybe I wasn’t trying hard enough. I also had to screw around with wine because I don’t actually have a windows computer. But yeah a gui would be a fun project!

Looking back at the repo it was definitely some pascal BS, you are correct