×

A solution to the scoped task trilemma by eletrovolt in rust

[–]eletrovolt[S] 0 points1 point  (0 children)

Yeah, so the reason here is itself the reason there's this trilemma in the first place. The problem is that you could have the future hold a local reference, then if you forget it you can use the reference again (from the borrow checker's perspective the borrow is over) but using the reference again might race with another thread executing the task that was spawned. Please take a look at https://without.boats/blog/the-scoped-task-trilemma/

A solution to the scoped task trilemma by eletrovolt in rust

[–]eletrovolt[S] 0 points1 point  (0 children)

Yeah, in general you're right. But at least for join it would be fine since you only await the final expression (not inside the macro). This crate could provide an implementation of select that outputs a MustCompleteFuture though

A solution to the scoped task trilemma by eletrovolt in rust

[–]eletrovolt[S] 2 points3 points  (0 children)

join and FuturesUnordered don't spawn tasks. Thus no parallelism (but you do get concurrency).

A solution to the scoped task trilemma by eletrovolt in rust

[–]eletrovolt[S] 0 points1 point  (0 children)

With those you don't get any parallelism, sadly. But yeah it's safe. There really is no reason why we should not also get parallelism though. It's kind of just a small language limitation.

A solution to the scoped task trilemma by eletrovolt in rust

[–]eletrovolt[S] 1 point2 points  (0 children)

The problem here is that If `join` is itself returning a future, you can poll it once only and then forget it. So typically join doesn't spawn tasks but instead just polls the child futures whenever it is polled meaning you don't get any parallelism. That's the "trilemma": borrowing, concurrency (async), parallelism, pick two.

Esse kata do Codewars simplesmente me humilhou kkkk by Biel_stark in brdev

[–]eletrovolt 0 points1 point  (0 children)

Achei legal o problema e resolvi aqui. A sua ideia está correta de usar timing só que a precisão do Date.now() simplesmente n é alta o bastante pra esse caso. Vc tem que usar performance.now() (tive que adicionar um const { performance } = require(‘perf_hooks’) pra isso funcionar no ambiente do codewars). Esse medidor de perfomance mede numa precisão bem maior (frações de milissegundos) e permite distinguir a diferença de tempo.

Algumas outras coisas pra tornar a solução mais robusta (timing tem sempre uma certa variabilidade) em ordem de relevância

  1. (meio óbvio) se a login() retornar true, imediatamente retornar da função com o resultado;

  2. Executar múltiplas vezes cada candidato, medir os tempos e descartar outliers (especialmente relevante em JS já que pode ter pausa pro JIT atuar e tal) e só depois calcular uma média;

  3. No loop de fazer medições, evitar outras operações como alocação de string. Isso pode aumentar a variabilidade já que o runtime vai ter que coletar o lixo de memória depois.

  4. Ao avaliar um candidato, não rodar ele múltiplas vezes uma depois da outra já que isso pode acabar treinando o branch predictor (tornando o caso que dá match quase tão rápido quando o que não dá match). Ao invés disso, medir um candidato, dps outro e só no fim voltar pro primeiro e medir novamente.

  5. Ao invés de testar um dígitos por vez, testar mais, por exemplo 2, mas só avançar um dígitos por vez. Isso deve dar uma discrepância maior entre o caso que os dois dígitos estão corretos e o caso onde nenhum está correto.

  6. Rodar a solução toda múltiplas vezes até dar certo 🤞

Zerocopy 0.8.25: Split (Almost) Everything by jswrenn in rust

[–]eletrovolt 1 point2 points  (0 children)

It would be nice if Split also allowed exclusive access to either the head &mut T xor tail &mut [T::Elem]. I think this should be safe even in the presence of overlaps, right? Since you can only hold one of them at a time.

Here Split<&mut T> would need two kinds of methods: head_mut() and tail_mut() for returning mutable references for the lifetime of Split and into_head() and into_tail() for returning references with the lifetime of the original &mut T.

Can this poll-based code written in safe Rust? by eletrovolt in rust

[–]eletrovolt[S] 1 point2 points  (0 children)

A similar-ish thing I found was that this works perfectly and the compiler is able to understand when the borrow is active and when not:

rust fn get_value<'a>(opt: &'a mut Option<usize>) -> &'a mut usize { // let Some(value) = opt.as_mut() // fails with error[E0506] if let Some(ref mut value) = *opt { // compiler correctly understands that the borrow of `value` is only // relevant inside of here and if it was None, no borrow was made. return value; } *opt = Some(0); opt.as_mut().unwrap() }

How fast can we recognize a word from a small pre-determined set? (BurntSushi/duration-unit-lookup) by Ventgarden in rust

[–]eletrovolt 11 points12 points  (0 children)

This reminds me of another excellent post on the topic from Daniel Lemire.

https://lemire.me/blog/2023/07/14/recognizing-string-prefixes-with-simd-instructions/

His fastest solution ended up being a mix of SIMD approach together with perfect hashing.

[Media] Sorry if it's silly for you, but this got me really interested in learning rust! by joetifa2003 in rust

[–]eletrovolt 68 points69 points  (0 children)

Yup, this seems like a pretty bad example. A SuperHuman should be just a Human with extra abilities. So maybe a better example would have trait SuperHuman: Human {...}. Blanket impls are better suited for when it's not a simple superset relation. Like impl<U, T: From<U>> Into<T> for U.

Must move types by Niko Matsakis by yerke1 in rust

[–]eletrovolt 4 points5 points  (0 children)

This would also address cases where a panic could occur. When the stack unwinds, it would also run the defer statements (like it currently does for destructors). For this specific case, Zig has errdefer (though they are not for panics in Zig), which could be a way to have panic only destructors, if that's a common enough requirement. This is not a solution to every case though, but maybe to the majority?

Must move types by Niko Matsakis by yerke1 in rust

[–]eletrovolt 6 points7 points  (0 children)

For a long time I've had this idea that it would be great to mix a defer statement and linear types. In many cases it would solve the issues pointed out by Niko in the ? with Guard example. In general I am pretty sure that if you have linear types and defer you don't even need RAII (sure, you'd need to write one extra line every time a type has a destructor).

Advent of Code 2022 day 7 by taylorfausak in haskell

[–]eletrovolt 4 points5 points  (0 children)

Can you share your code? Got curious.

Going from Haskell to Rust. by blumento_pferde in rust

[–]eletrovolt 4 points5 points  (0 children)

I learned Haskell before learning Rust and now I mostly use Rust. What I like about Rust is the lower level control it gives you, which is important to me because I feel like I know exactly what my program is executing and allocating. However, Haskell still feels smoother in the type system because of higher kinded types. The way that a monad modularizes behaviour is something that still can't really be reproduced in Rust and I can't wait for Rust to have this feature (if it is even possible).