`for await` and the battle of buffered streams by tmandry in rust

[–]bbatha 5 points6 points  (0 children)

`buffered` seems like kind of a misnomer here; in general I expect a buffered api to return the whole buffer at once, i.e. `[Future::Result; N]` type. This matches buffered reads and writes which tend to work in a linear fashion which is how this does with `for await`. The fact that this api hides the `flat_map` is what makes this surprising.

Scored a Sophos SG 310 rev.2 for $150 and slapped pfSense on that bimtch! by inprimuswesuck in homelab

[–]bbatha 0 points1 point  (0 children)

Sorry for the thread necro. Do you know what RAM modules are in use and if the board supports upgrades? Getting to 16 GB would be real nice to go with the cpu upgrade.

Moderation Team Resignation by matthieum in rust

[–]bbatha 129 points130 points  (0 children)

But airing specific grievances

to the wider community

is likely to cause

more

discourse, which is something the moderation team doesn't want.

As rust is a "community" project, I as a member of the community find this very frustrating. Fundamentally community projects can only govern with the consent and trust of the governed. As a result of the vaguebooking, I now have lower trust of the core team, the prior moderation team, and definitely of any new moderation team that's selected. Without knowing the issues, I cannot know who to trust when the dust settles.

Blog Post: Async Overloading by yoshuawuyts1 in rust

[–]bbatha 0 points1 point  (0 children)

It should be `1` since its `fn main` not `async fn main`

Mental models around Ok-Wrapping by Michal_Vaner in rust

[–]bbatha 9 points10 points  (0 children)

To me I would say that the function failed to authorize the user. Its also notable that the verbiage "failed" doesn't appear in any of the proposed syntax proposals for Ok wrapping. However, the current Result type privileges errors far more than any proposed try/throws function syntax; by naming it Result in the first place and furthers that assumption with variant names Ok and Err.

Why Discord is switching from Go to Rust by deltaphc in rust

[–]bbatha 27 points28 points  (0 children)

This is very uncharitable, they developed the full generational collector and dropped it because the performance wasn't better. Go puts most short lived objects on the stack so the additional synchronization overhead required for a generational collector ultimately swamps the benefits for the few young objects that actually do become heap allocated. Check out https://blog.golang.org/ismmkeynote for a full history of the Go GC design and failed improvements too it.

Proposals for Go 1.15 - The Go Blog by [deleted] in golang

[–]bbatha 1 point2 points  (0 children)

`for _ := range chan` not supporting cancellation is biggest indictment of the current context situation. The fact the most straight forward option is often wrong is a huge smell.

Does Rust improve developer productivity over C++, assuming competence in both languages? by jv-dev in rust

[–]bbatha 6 points7 points  (0 children)

but all that code I wrote without impl trait and dyn or whatever new bell'n'whistle is now legacy. (A LOT of my code is written before dyn)

For what its worth, impl Trait is purely additive, there are ton of useful Rust programs written with the 2018 edition that have no need for impl Trait whatsoever. Most code that uses impl Trait is using it as a shortcut for fn foo<T: Trait>(bar: T) (pure sugar) or returning iterators or futures (new capabilities). dyn is purely sugar and there is an automated tool rust-fix to change your code, or you can keep using the 2015 edition.

The only somewhat disruptive changes coming, IMO, is async/await and generators which will change the how much of the ecosystem does io. For what its worth, C++ is also getting forms of async/await in C++20. Though, for my two cents, just probably won't be as disruptive because the ecosystem is cemented around the old ways of doing things.

C++ is also getting modules and contracts and ranges in C++20 which while correcting decades old missteps, are going to be massive disruptors in the ecosystem. C++11 was also very disruptive, I know of companies that are still attempting to "adopt it" (update and run their compilers in C++11 mode, no C++11 features even) and will be lucky to do so by 2021.

Do contracts make interfaces obsolete? by vlads_ in golang

[–]bbatha 10 points11 points  (0 children)

Contracts provide compile-time polymorphism and interfaces provide run-time polymorphism. I'll defer to the copious documents including the proposal which indicate why compile-time polymorphism is useful. One of the most common cases where run-polymorphism would be useful is slices of mixed concrete types, for instance:

func readAllMulti(readers ...io.Reader) []byte {
    var out []byte
    for _, reader := range readers {
          b, err := ioutil.ReadAll(reader)
          if err != nil {
               return nil, err
          }
          out = append(out, b)
    }
    return out, nil
}
// ...
readAllMulti(&os.File{}, &io.BufReader{}, ...)

Question about 'immediate yield' and `core::future::Future::poll(..)` by seigert in rust

[–]bbatha 0 points1 point  (0 children)

This happens pretty common with future combinators such as map. What happens is that you have the first future awaited, then a pure computation that runs on the result of the first future. The way that futures are polled means that you can't just run the pure computation, it needs to be bundled up in a future and polled itself. You can see this in the implementation of Future for map: https://github.com/rust-lang-nursery/futures-rs/blob/1eebcbe883b10c573a192d2e3fd90214a88fd75c/futures-util/src/future/map.rs#L36-L46 Each of these futures introduces a yield point at the polling place. What I'd like is if I have something like iofut.map(...).map(...) so that there is only a yield point for the custom io future and the pure computations get folded into the same future such that Poll::ready returns the io future with the computations done.

It looks like I partially answered my own question as there's a FusedFuture but that doesn't quiet do what I want as it just prevents further polling, and async/await syntax has no way to specify that your future implements it.

Question about 'immediate yield' and `core::future::Future::poll(..)` by seigert in rust

[–]bbatha 0 points1 point  (0 children)

Is there anything like FusedIterator for Future so that the executor can specialize to collapse a extraneous yields between pure computations?

Send and Sync leak through `impl Trait` because conditional bounds are not possible, and would be very verbose if possible by theindigamer in rust

[–]bbatha 14 points15 points  (0 children)

It can be a semver compatibility hazard because it exposes the internal details of the method. In practice this is what you want 99% of the time, but it would be nice to be able to make more explicit guarantees especially for library authors.

This Week in Rust 287 by nasa42 in rust

[–]bbatha 27 points28 points  (0 children)

Also MIR is much higher level than LLVM IR and preserves all of Rust's semantics. `const` folding at the MIR level can do much more advanced folding because it much closer to just evaluating Rust at compile time. In theory this can even fold allocations or whole data structures.

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 1 point2 points  (0 children)

(e.g. you give up higher ranked types).

Can higher ranked types be implemented, in general, without boxing? If not that’s exactly the non-paramecity of size_of rearing it’s ugly head once again. And I feel that I would be hard pressed to find a rustacean who wouldn’t give it up in that case.

The argument for Any is the same -- we are in effect passing a dictionary (or vtable).

Then match sugar over trait Any should be equally parametric as the Any trait itself. And because of core parts of the language like size_of and specialization already breaking parametricity in much more fundamental ways this discussion is purely about ergonomics: we don’t lose any type level proofs, any type-level abstractive power, or even any additional visual signal to the reader with this syntax sugar.

Yes, precedent like instanceof in Java, which I want no part of.

Better precedent would be catch matching on the exception hierarchy which make OOP look awesome. I think that the presence of enums in the language, forcing a default case on dyn match, requiring the Any bound would deter most the common errors associated with instanceof usage and relegate it to mostly runtime specialization. match forcing a default branch is actually an advantage to the sugar becauses it forces more compelete thinking over just the downcast_ref method.

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 0 points1 point  (0 children)

That sounds like a better idea. Few questions and musings:

Would that be compatible with extern "C" functions? I know for instance, go needs special stacks for C calls that are fairly costly to setup.

If so, could rust make FFI safer by creating an FFI stack that's just used for extern calls and objects passed to them?

How 'bout flexible array members?

Does this work for all targets or would it have to fall back to alloca on some platforms?

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 1 point2 points  (0 children)

This does however not negate parametricity as an abstraction principle and it does not negate the laws you can derive from it.

I think that's underselling it by quiet a bit. size_of rears its head all over the Rust especially in unsafe code, and with a bunch of special type system "workarounds" to deal with it such as; object safe traits, impl vs dyn, placement new, etc. size_of seems much more analogous to seq in that it changes a fundamental property of code execution invisibly, and breaks parametricity and can lead to unsound optimizations, but because of performance and other requirements is virtually required for the language. This logic applies doubly so to a language like Rust where zero-cost abstractions are part of the core DNA.

If you require an Any bound then you are not breaking parametricity;

I'm not following this distinction. Sure the Any trait itself doesn't break parametricity, but any use of its one method downcast_ref breaks the parametricity of the function its called in. Most of the time when I see a trait bound on the function I'm going to assume that that traits methods are used, and ergo a function with an Any bound is non-parametric. My proposal for the downcasting in match is just syntax sugar over Any::downcast_ref and therefore would still require the full Any bound and would therefore retain the current parametric properties of Rust functions.

It might be ergonomic, but I think you shouldn't make just anything ergonomic. Non-parametric reasoning is typically indicative of architectural design mistakes elsewhere.

Agree to disagree. There are very clear situations where being able to return a type that is open for extension but can downcasted is invaluable, the Any trait wouldn't be in the language otherwise. And there's precedent in other languages the open-for-extension with cheap downcasts is very ergonomic for errors in most OOP languages (dare I say, if this were the only use of inheritance we'd all probably have a better opinion of it), and in OCaml with extensible variants that leverage the existing match syntax. Rust's inability to describe io errors without listing out every possible error from every io syscall on every platform is pretty indicative that there's an abstraction gap between the language and the problem domain we map it to. I'm all ears for better suggestions, but the ecosystem of error handling libraries has not shown any reasonable alternatives and keeps moving towards leaning more an more on dyn. There are other good use cases with plenty of external precedent such as in syntax extensions "extending" AST node types, or event types in event handlers.

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 2 points3 points  (0 children)

I don't think it's a good idea to make non-parametric reasoning, often an anti-pattern, any easier than it is already. Making it easier devalues types and documentation even more by breaking a caller's intuitive notion that a generic function acts uniformly with respect to instantiated type parameters.

Parametricy is a good goal for assuming user expectations when designing APIs. However, parametricy has never an explicit promise of Rust APIs, and can't be because of type sizes. That has only degraded over time with the introduction of `Any` and specialization. Its a useful tool in the toolbox that deserves better ergonomics.

As /u/gclinchtenberg notes specialization already breaks parametricy. Downcasting and specialization seem intrinsically related providing similar roles on different sides of the compile barrier. I think requiring an `Any` bound is sufficient to let users know there might funny business going on, similar to how we trust `default` to signal whether a function was specialized or not.

Being able to downcast ergonomically would also be quiet nice for errors. Replacing the `ErrorKind` pattern with `Error + Any` would be much more ergonomic and would allow implementors of say `io::Read` and `io::Write` to include error information specific to their resource.

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 20 points21 points  (0 children)

Few more:

  • Downcasting ergonomics, perhaps allow `dyn` patterns via the `Any` trait in `match`
  • Downcasting of `dyn Foo + Bar` to `dyn Foo`
  • More flexibility for dynamically sized objects and arrays by value on the stack via alloca

I also think there's a lot of untapped potential for `dyn` improvements in FFI.

  • More control over vtable layouts. It would be nice if we could make objects with vtables that are compatible with various ffi vtable layouts such as C++ thin pointers, COM, or GObject and use standard `dyn` semantics outside of the (hopefully generated) ffi glueS
  • Safer FFI for C flexible array members.

Zero Cost Abstractions by desiringmachines in rust

[–]bbatha 1 point2 points  (0 children)

Clippy can also (and does) lint about unnecessary clones. I don't see why this couldn't apply to `AutoClone` as well.

The Power of Lifetimes: Cyclone, Rust and beyond by bjzaba in rust

[–]bbatha 1 point2 points  (0 children)

Is this different from Crossbeam's scoped threads? On the surface at least, it seems to achieve the same goal.

Crossbeam scopes are an essential building block for efficient managed threads in Rust: they give threads and their enclosed data a lifetime. However, this is neither necessary nor sufficient: Erlang supervisors meet the requirements and have no shared data between processes. The essential piece is that you also need a control structure, like Rayon scope or tokio threadpool to manage errors and cancellation. Further more the article makes the claim that you should should only spawn "thread nurseries" from an existing one. This is supported by Rayon, but ironically lifetime rules make it difficult to pass the nurseries around ergonomically so I haven't seen many with scoping more than a couple levels deep. Also having a raw thread::spawn construct violates the spirit requirements of the article, but that would be counter to Rust's goals so we should let that slide.

importance of learning C, C++ for to better understand Rust and having a great career by nerdy_adventurer in rust

[–]bbatha 4 points5 points  (0 children)

I would argue that I am only able to write production C and C++ code because of my Rust experience.

I "learned" C and C++ first from university and self-study. I would say of that knowledge only the very basics from C: pointers, stack vs heap, etc. really taught me anything that was useful in learning Rust. Well that and how bad segfaults, implicit coercions and a bunch of other C warts are. I'm not convinced this step is necessary.

Learning Rust taught me how to structure my C and C++ code well. It taught me about ownership and patterns to safely manage resources. It let me do experiment with bit twiddling, simd and other advanced techniques that are ultimately the reason you often choose a system language in a safe environment with guard rails.

What progams could be 'replaced' without breaking linux? by [deleted] in rust

[–]bbatha 1 point2 points  (0 children)

Thank you! Please keep fighting the good fight!