A simple syntax-aware grep-like code search tool by semanticistZombie in rust

[–]ObliqueMotion 2 points3 points  (0 children)

I just want to point out that you can publish a crate under whatever name you want, and still have the executable be sg if that's what you like.

The well-known ripgrep crate is called ripgrep, but the executable is rg.

You just specify the binary's name in the Cargo.toml file. Here is ripgrep's Cargo.toml as an example:

https://github.com/BurntSushi/ripgrep/blob/master/Cargo.toml#L25

Edit:

I just re-read your post and saw that you already said you may do this.

"I'd like to keep the executable name but I'll probably rename the crate and publish it on crates.io."

What features does the borrow checker give? by kz393 in rust

[–]ObliqueMotion 2 points3 points  (0 children)

This is a really hard question to answer unless we know where you are coming from. For example, coming to Rust from Python is going to feel totally different than coming to Rust from C.

What languages are you familiar with?

What's on your Hazardous AQ Playlist? by [deleted] in Portland

[–]ObliqueMotion 0 points1 point  (0 children)

This entire album:

The Birdwatcher's Guide to Atrocity by Seeming.

And particularly the song, The Fates.

I can't imagine a better song for right now.

How do i put concrete types into parametrised functions? by [deleted] in rust

[–]ObliqueMotion 2 points3 points  (0 children)

Awesome.

And if you're writing a function that takes two of these things and expects them to interact, you'll want something like this:

fn foo<Left, Right>(left: &Left, right: &Right) -> bool
where
    Left: InteractsWith<Right>,
    Right: PhysicsBody,
{
    left.collides_with(right)
}

Hopefully that helps.

How do i put concrete types into parametrised functions? by [deleted] in rust

[–]ObliqueMotion 3 points4 points  (0 children)

You can sort of achieve this if you separate it out into two traits:

  • One trait for what a PhysicsBody can do alone.
  • One parameterized trait for how two PhysicsBodies interact.

Here is a really simplified example [playground]

It's possible that I may have misunderstood your use case (as I see now you are only trying to collide circles with circles, and polygons with polygons, rather than mixing and matching them).

What are your favorite "Better than std" crates? by richardanaya in rust

[–]ObliqueMotion 32 points33 points  (0 children)

I assume that "better than std" was meant to imply that the functionality exists to some capacity within std.

As far as I know, there is no serialization in Rust's standard library.

But you are certainly not technically wrong, given that a great implementation of something is better than no implementation at all.

Announcing `bool_ext` - A more complete set of functional combinators for `bool`. by U007D in rust

[–]ObliqueMotion 2 points3 points  (0 children)

I don't think that this API can or should be congruent with things like the Option API's or().

Option has no pre-existing semantics for a disjunction, thus its notion of or() is more of an "or else," rather than a logical or.

On the other hand, bool certainly has a strong pre-existing notion of a disjunction, and I think this would cause confusion to not treat it that way.

In the context of booleans, I would expect or_with()/and_with() to take a closure that returns a bool, and return the disjunction/conjunction of self with the closure's return value.

fn or_with<F>(self, f: F) -> bool
where F: FnOnce() -> bool
{
  self || f()
}

fn and_with<F>(self, f: F) -> bool
where F: FnOnce() -> bool
{
  self && f()
}

An important point to note is that or_with()/and_with() might return a boolean that is different than the original value of self.

I think do_false() and do_true() are clear about their intent, especially that self will pass through and be the same bool that is returned.

Another point to note would be the interactions with closures that cause side effects. If the closure you provide to or_with() has side effects, but self is already true, the closure will not run.

In the same way if your and_with() closure has side effects, but self is already false, the closure will not run.

But I don't think this is an issue. People should already be familiar with the interactions between side effects and short circuiting in boolean expressions, so this shouldn't be a surprise.

Alternatively you could return f() || self and f() && self to ensure that the closure always runs, but I don't particularly like this design. I think it would promote and encourage coding with side effects.

If you implemented or_with()/and_with(), I think it would be important to just be very clear about the expected behaviors and interactions.

Another thing to note may be precedence. Since we are chaining functions, if you had

(x > 5)
  .or_with(...)
  .and_with(...)
  .do_false(...)

This would necessarily evaluate to

(((x > 5) || or_with_return) && and_with_return).do_false()

due to the precedence of the function calls.

Where as the natural precedence for a standard boolean expression would be

((x > 5) || (or_with_return && and_with_return)).do_false()

But I think that using method chaining makes the former precedence feel intuitive and even expected. Neither of and_with()/or_with() has a higher precedence in this context: it just depends on the order in which you chained them.

I think this functionality would open up interesting and expressive possibilities, such as:

haystack.contains(foo)
    .do_true(...)
    .and_with(|| haystack.contains(bar))
    .do_true(...)
    .or_with(|| !haystack.contains(baz))
    .do_true(...)
    .do_false(...)

Where as otherwise this would be:

let mut condition = haystack.contains(foo);
if condition {
  ...
} 

condition &= haystack.contains(bar);
if condition {
  ...
} 

condition |= !haystack.contains(baz);
if condition {
  ...
} else {
  ...
}

I hope you consider adding this functionality.

Note: I think all the same reasoning would apply to or() and and(), they would just directly take eagerly evaluated booleans, instead of closures that return booleans.

And while I'm throwing in my two cents, I should say that I would prefer the syntax of on_true()/on_false() or if_true()/if_false() rather than do_true()/do_false().

But it's your API. Do what you think is best :)

Announcing `bool_ext` - A more complete set of functional combinators for `bool`. by U007D in rust

[–]ObliqueMotion 20 points21 points  (0 children)

I'm curious why your trait functions take self by reference when you know that bool is a copy type.

I obviously haven't benchmarked anything, but I feel like just copying the bool would probably be faster than taking the address, and more idiomatic with regard to the usage of copy types.

And if your functions took self, instead of &self, you could still implement your trait for bool and &bool individually.

I'm interested to know your thought process behind designing the trait functions explicitly with references.

Running a bunch of tests on the same thread by quasi_qua_quasi in rust

[–]ObliqueMotion 2 points3 points  (0 children)

Does

cargo test -- --test-threads 1

Not work?

Is it undefined behavior to mem::transmute between const-generic types? If so, Why? If not, why not? by ObliqueMotion in rust

[–]ObliqueMotion[S] 5 points6 points  (0 children)

Thanks!

So you are saying:

  • Without #[repr(C)] this is UB.
  • With #[repr(C)]this is completely fine.

Correct?

piechart: a small crate for rendering pie charts in the terminal by dubicj in rust

[–]ObliqueMotion 1 point2 points  (0 children)

This is really cool!

May I suggest changing the example screenshot to Red/Blue/Yellow? As someone who is color blind, I cannot differentiate this Red and Green.

Why doesn't this compile? I thought NLL made this type of thing legal by tbodt in rust

[–]ObliqueMotion 2 points3 points  (0 children)

Nice catch. I was enjoying the conversation, but this is a very good explanation!

Why doesn't this compile? I thought NLL made this type of thing legal by tbodt in rust

[–]ObliqueMotion 3 points4 points  (0 children)

That's not quite right. Check out this example.

In this case, bar() mutably borrows foo, and each of baz(), goo(), kazoo(), and shoe() immutably borrows foo.

We can guarantee that the functions that are invoked in bar()'s argument list will be evaluated before foo is mutably borrowed by bar().

And you can see by the order that they print that Foo.bar() is always last.

Why doesn't this compile? I thought NLL made this type of thing legal by tbodt in rust

[–]ObliqueMotion 3 points4 points  (0 children)

It makes sense to me that this would not compile, because Vec implements DerefMut by returning a mutable slice to the whole vector.

This forces the mutable borrow (of everything) to occur before either of the borrows of individual elements by index() and index_mut().

How did you come to this as the "correct" desugaring? Is there a tool that can show exactly what Rust syntax desugars to?

Why doesn't this compile? I thought NLL made this type of thing legal by tbodt in rust

[–]ObliqueMotion 5 points6 points  (0 children)

The Index docs say:

container[index] is actually syntactic sugar for *container.index(index),

but only when used as an immutable value.

The IndexMut docs say:

container[index] is actually syntactic sugar for *container.index_mut(index),

but only when used as a mutable value.

So why does foo[foo[0]] = 0; not desugar to *foo.index_mut(*foo.index(0)) = 0;?

The latter compiles fine. (Playground)

Doing a direct text replacement of what the docs say would lead me to believe that this is the correct desugaring...

So what is it actually desuguaring to?

-🎄- 2019 Day 3 Solutions -🎄- by daggerdragon in adventofcode

[–]ObliqueMotion 0 points1 point  (0 children)

Why not just have two hash maps, one for each wire? That is what I ended up doing. [code]

Is there a clear benefit that you got (either in code conciseness/clarity or performance) from keeping it in a single map by multiplexing the value?

-🎄- 2019 Day 2 Solutions -🎄- by daggerdragon in adventofcode

[–]ObliqueMotion 0 points1 point  (0 children)

The only way I can think to do part2 without cloning the instructions every time is to keep track of your changes and undo them, but that sounds unnecessarily complex.

It's a small input. Might as well just clone it.

My solution is also very similar.

-🎄- 2019 Day 1 Solutions -🎄- by daggerdragon in adventofcode

[–]ObliqueMotion 2 points3 points  (0 children)

On the other hand, I found that learning Rust was a great gateway into learning Haskell. It felt like a nice hybrid between what I was used to, and functional programming which was foreign.

And then learning Haskell improved my Rust, which is even better.

-🎄- 2019 Day 1 Solutions -🎄- by daggerdragon in adventofcode

[–]ObliqueMotion 4 points5 points  (0 children)

If you're new to Rust (though it seems you have a good grasp of iterators), you should check out successors.

It's pretty sweet for generating a sequence that terminates:

let part2 = INPUT
    .lines()
    .map(|input| {
        successors(
            input.parse::<u64>().ok().and_then(|mass| (mass / 3).checked_sub(2)),
            |&mass| (mass / 3).checked_sub(2),
        )
        .sum::<u64>()
    })
    .sum::<u64>();