这个 SO答案使用了where
我不熟悉的语法:
fn readfile<'a, T: ?Sized>(filename: &str) -> Result<Box<Outer<'a, T>>, Box<std::error::Error>>
where
for<'de> T: Deserialize<'de> + 'a
{
...
Run Code Online (Sandbox Code Playgroud)
这是什么for
意思?
这是在哪里记录的?
我有一个复杂的 JSON 文件,我只想从中提取一个值。我可以定义所有struct
s 并Deserialize
在所有这些s 上派生,但我只想编写一些手动代码来提取那个值。该SERDE文档,坦率地说,只是让我感到困惑。
我的 JSON 内容具有以下布局:
{
"data": [
{
"hostname": "a hostname"
}
]
}
Run Code Online (Sandbox Code Playgroud)
我正在寻找通过进入导航到的值data
,然后获取数组的第一个元素,并获取hostname
.
在 Haskell 中,我会这样做:
{
"data": [
{
"hostname": "a hostname"
}
]
}
Run Code Online (Sandbox Code Playgroud)
Serde 的等价物是什么?
我有以下类型签名的许多功能:
fn f() -> impl Fn(u32) -> u32 {
|x: u32| x
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能给它一个名字,Fn(u32) -> u32
这样我就不必重复它了?尽管我可以做到type X = Fn(u32) -> u32;
,但 Rust 不会让我使用它,因为它是一种类型而不是特征。我必须等待trait_alias
还是可以做其他事情?
如果我有一个数字列表,[1, 2, 3, 4, 5]
并且想生成一个累积总数列表,那么在Haskell中,我将执行以下操作:
> let xs = [1, 2, 3, 4, 5]
> scanl (+) 0 xs
[0,1,3,6,10,15]
Run Code Online (Sandbox Code Playgroud)
在Rust中,尝试获得相同的行为似乎不必要地麻烦。
let xs = [1, 2, 3, 4, 5];
let vs = vec![0]
.into_iter()
.chain(xs.iter().scan(0, |acc, x| {
*acc += x;
Some(*acc)
}))
.collect::<Vec<_>>();
Run Code Online (Sandbox Code Playgroud)
scan
缺少GC可以解释必须使累加器发生突变的尴尬行为。但是,scan
还不包括初始累加器值,因此需要在前面手动添加0。这本身很麻烦,因为我需要用加前缀chain
和[0].iter()
没有工作,也没有[0].into_iter()
和vec![0].iter()
。它需要vec![0].into_iter()
。
我觉得我在这里一定做错了。但是呢 有没有更好的方法来产生累计和?回到for
循环了吗?
以下代码因借用错误而失败:
extern crate chrono; // 0.4.6
fn main() {
let mut now = chrono::Local::today();
now = std::mem::replace(&mut now, now.succ());
}
Run Code Online (Sandbox Code Playgroud)
错误是:
extern crate chrono; // 0.4.6
fn main() {
let mut now = chrono::Local::today();
now = std::mem::replace(&mut now, now.succ());
}
Run Code Online (Sandbox Code Playgroud)
为什么这里会出现借用错误?now.succ()
返回一个新对象,看起来调用succ()
应该返回新对象,在可变借用发生之前结束不可变借用replace
。
Haskell的翻页功能定义如下:
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
Run Code Online (Sandbox Code Playgroud)
它所做的只是获取一个函数并返回另一个具有两个相反参数的函数。如果你调用的函数f
为f a b
(f(a, b)
鲁斯特的语法),你会叫flip f
的(flip f) b a
。
我在Rust中编写此文件的尝试失败:
fn flip<A, B, C, F: Fn(A, B) -> C>(f: F) -> impl Fn(B, A) -> C {
|a, b| f(b, a)
}
Run Code Online (Sandbox Code Playgroud)
可以用Rust写这个吗?
考虑以下工作代码:
\n\nfn f() {\n let xs = vec![(0, 0)];\n let f = |j| xs[j];\n let y = f(0usize);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n以下变体无法编译:
\n\nfn f() {\n let xs = vec![(0, 0)];\n let f = |j| xs[j].0;\n let y = f(0usize);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n它失败如下:
\n\nerror[E0282]: type annotations needed\n --> src/lib.rs:3:17\n |\n3 | let f = |j| xs[j].0;\n | ^^^^^ cannot infer type\n |\n = note: type must be known at this point\n
Run Code Online (Sandbox Code Playgroud)\n\n要修复它,必须注释j
:
fn …
Run Code Online (Sandbox Code Playgroud) 假设我有如下 JSON 数据:
{
"type": "A",
"value": [ 1, 2, 3, 4, 5 ]
}
Run Code Online (Sandbox Code Playgroud)
{
"type": "B",
"value": [ [ 1, 2, 3, 4, 5 ], [ 6, 7, 8 ] ]
}
Run Code Online (Sandbox Code Playgroud)
type
确定 的类型value
,在第一个示例中为Vec<u32>
,在第二个示例中为Vec<Vec<u32>>
。
如果我将上面的数据表示如下:
{
"type": "A",
"value": [ 1, 2, 3, 4, 5 ]
}
Run Code Online (Sandbox Code Playgroud)
如何实现 serde 反序列化以正确解码这些值?
我正在接收字符串矢量形式的数据,并且需要使用值的子集填充结构,如下所示:
const json: &str = r#"["a", "b", "c", "d", "e", "f", "g"]"#;
struct A {
third: String,
first: String,
fifth: String,
}
fn main() {
let data: Vec<String> = serde_json::from_str(json).unwrap();
let a = A {
third: data[2],
first: data[0],
fifth: data[4],
};
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为我正在将值移出向量。编译器认为,这会data
处于未初始化的状态,这可能会导致问题,但是由于我再也没有使用data
过,所以没关系。
常规解决方案是swap_remove
,但是这是有问题的,因为不能以相反的顺序访问元素(假设结构是从上到下填充的)。
我现在通过执行a mem::replace
并使用data
as来解决此问题mut
,这会使本来很干净的代码变得混乱:
fn main() {
let mut data: Vec<String> = serde_json::from_str(json).unwrap();
let a = A {
third: std::mem::replace(&mut data[2], "".to_string()),
first: std::mem::replace(&mut …
Run Code Online (Sandbox Code Playgroud) 我有以下实现目录漫游的模块:
module Walk
( walk
) where
import Control.Monad
import Control.Monad.IO.Class
import Data.List
import System.Directory
import System.FilePath
walk :: (MonadIO m) => FilePath -> m [(FilePath, [FilePath])]
walk root = do
entries <- liftIO $ listDirectory root
(files, dirs) <- partition snd <$> liftM2 (<$>) zip (mapM (liftIO . doesFileExist . (root </>))) entries
((root, map fst files) :) . concat <$> mapM (walk . (root </>) . fst) dirs
Run Code Online (Sandbox Code Playgroud)
它当前返回一个列表,但我希望它返回一个Traversable
:
walk :: (MonadIO m, Traversable t) => …
Run Code Online (Sandbox Code Playgroud)