Good to hear!
Programmer in NYC
Good to hear!
Well if you want to try another avenue, I’ve read about implementing self-referential structs using Pin
.
There’s a discussion here, https://blog.cloudflare.com/pin-and-unpin-in-rust/
There’s a deep dive on pins here, but I don’t remember if it addresses self-referential types: https://fasterthanli.me/articles/pin-and-suffering
Oh I’m sorry! I messed up my test case so it only looked like the block fixed things.
Did you try adding the block like I suggested? I reproduced the same error that you are seeing, and verified in my playground snippet that the block fixes the problem.
It’s ok that query_map references pstmt. Isolating pstmt in a block causes it to be dropped at the end of the block while rec_iter continues to live. I think that might be thanks to temporary lifetime extension or something.
Ok I have a simple solution for you. What you need to do is to produce rec_iter
in such a way that pstmt
is dropped at the same time. You can do that by creating and calling pstmt
in a block like this:
let rec_iter = {
let mut pstmt = conn.prepare(sql.as_str())?;
pstmt.query_map(/* ... */)?
};
Here is a Rust Playground example
I’m glad you found a workaround. I didn’t want to be defeated by the callback idea that I had yesterday so I worked on it some more and came up with a similar-but-different solution where ZnsMaker
stores pstmt
paired with a closure that borrows it. This is again a simplified version of your code that is self-contained:
The closure solution avoids the need to pass conn
to make_stream
. I don’t know if it would fix the new borrowing error that you got since I did not reproduce that error. But I think it might.
Does znsstream
need to outlive znsm
? If so I think my solution solves the problem. Does znsstream
need to outlive conn
? That would be more complicated.
Edit: Oh! You don’t need to put both the pstmt
and a closure in ZnsMaker
. Instead you can just store a closure if you move ownership of pstmt
into the closure. That ensures that pstmt
lives as long as the function that produces the iterator that you want:
Edit: Lol you don’t need ZnsMaker
after all. See my other top-level comment. I learned some things working on this, so time well spent IMO.
Well I’m curious to know what solutions there are to this. But I did reduce your problem to a smaller, self-contained example:
struct ZKNoteStream<'a, T> {
rec_iter: Box + 'a>,
}
struct BorrowedThing(Vec);
impl BorrowedThing {
fn prepare(&self) -> IterProducer<'_> {
IterProducer(&self.0)
}
}
struct IterProducer<'a>(&'a Vec);
impl<'a> IterProducer<'a> {
fn query_map(&self) -> impl Iterator {
self.0.into_iter()
}
}
fn test(conn: &BorrowedThing) -> ZKNoteStream<'_, &String> {
let pstmt = conn.prepare();
let rec_iter = pstmt.query_map();
ZKNoteStream { // cannot return value referencing local variable `pstmt`
rec_iter: Box::new(rec_iter),
}
}
Edit: Wow, that code block came out mangled. Here is a Rust Playground link
I ran into a similar problem yesterday, but it was a case where I had control over all the code. What I did was the equivalent of changing query_map
so that instead of taking a reference to its receiver, it takes ownership.
My thinking at the moment is that you may need to modify ZKNoteStream
so that instead of containing the resulting iterator it contains pstmt
, maybe paired with a function takes pstmt
as an argument and returns the iterator. It seems like you should be able to create an FnOnce
closure with a move
keyword that moves ownership of pstmt
into that closure, which you could then store in ZKNoteStream
. But I’m not able to make that happen right now.
This is what I use. Or if you don’t need image/PDF embedding or mobile support then VimWiki is a similar solution that is FOSS.
This is an interesting idea! When I was learning Nix, and feeling frustrated, I often thought that a type-checked language would help with discoverability. But it seems like it might be difficult to combine strong type-checking with Nix expressions’ use of lazy self-reference. So with Garn you get the type-checking, but lose the laziness. I’m interested to see how that goes.
Thanks for the tip about nu_scripts, those look handy!
The expand command is nice. I don’t see how to use it to my mv command work. But that’s not a huge deal.
So maybe this is too much of a kludge, but I happened to see that you can define custom sub-commands to extend existing commands. You can use that to reproduce your familiar command:
def "ls -lrt" [] {
ls | sort-by modified | reverse
}
Of course this does not capture the usual composability of those switches.
Well I might be hooked. It didn’t take me long to reproduce the niceties in Nushell I’m used to from my zsh config. Some of the important parts were setting up zoxide with a key binding for interactive mode, switching on vi key bindings, setting up my starship prompt.
Home Manager is preconfigured for the above integrations which made things easier.
One feature that is missing that I like to use is curly brace expansion to produce multiple arguments. For example,
$ mv *.{jpg,jpeg}
Unless there is a way to do something like this in Nushell that I haven’t seen yet?
Something I enjoyed was automating a sequence of steps I’ve been running a lot lately due to a program that often partially crashes,
def nkill [name_substring] {
ps | where name =~ $name_substring | each { |p| kill $p.pid; $p }
}
I realized after writing this that I basically recreated killall -r
. But it’s nice that it was so easy to make a custom command to do a very specific thing. And my version gives me a nice report of exactly what was killed.
Thanks for making this post OP! When I’ve heard mentions of Nushell I’m the past I think I conflated it with Powershell, and wrote it off as a Windows thing. (Maybe because it’s introduced as being “like Powershell”.) But now that I see that it’s cross-platform I’m enjoying digging into it!
I think the best way to get an idea is to look at feature lists for fancy shells like zsh or fish. But in short there are a number of things a good shell can do to help to execute commands faster and more easily. Stuff like autocompletions which make you faster, and also make things more discoverable; fuzzy searching/matching; navigating command history; syntax highlighting which helps to spot errors, and helps to understand the syntax of the command you’re writing.
I did not realize nano implemented syntax highlighting!