让我们随机抽取一段写得很好的锈蚀代码:
let shader = device.create_shader_module(&wgpu::ShaderModuleDescriptor {
label: Some("Shader"),
flags: wgpu::ShaderFlags::all(),
source: wgpu::ShaderSource::Wgsl(include_str!("shader.wgsl").into()),
});我远不是一个铁锈专家,但让我感到奇怪的是,我必须输入大量的符号。
例如,如果我们将上面的段落改写成或多或少的习语Swift,我们就会得到以下内容:
let shader = device.createShaderModule(
label: "Shader",
flags: .all,
source: String(contentsOfFile: "shader.wgsl")!,
)或者,如果它是用Javascript编写的,我们可以想象它的样子:
let shader = device.createShaderModule({ label, flags, source })是的,我有点作弊,但重点仍然是:其他新的波语言用30.50%的击键来表达类似的概念。
虽然我理解并欣赏Rust语言设计人员通过帮助编译器使用明确的语法、显式名称等来保持低编译时间的意图,但我仍然觉得需要一些时间来习惯以我通常的速度浏览来自其他语言的源代码。虽然锈蚀代码确实在代码中编码了更多的信息--比如生命周期--但在上下文中它仍然显得多余。我也觉得可能有一种更符合人体工程学的方法来用“锈”来写作。
对不起,如果我的问题被认为是挑剔或不服从--我确实是个菜鸟,所以请宽恕我。在这个问题上,我想要了解的是,我是否可以在我的锈蚀代码中增加信噪比,同时仍然是惯用的。
Rust程序员是否对如此长的限定符感到总体满意,并且需要一些时间来适应它,还是我错过了一种方法来提高我的Rust代码的信息密度?
发布于 2021-05-30 16:04:43
没有人指责罗斯特简明扼要。虽然它重视“人机工程学”,但它更重视控制、精度和稳定性。
例如,Rust不支持命名参数,因为Rust社区不相信它已经有了一个实现命名参数的设计,该设计可以很好地工作。因此,常见的解决方法是创建一个结构来绑定一些参数。而结构化文字需要一个命名类型。
另一个相当基本的设计决策是缺乏隐式矫顽力。例如,类型不是隐式可空的-您需要显式地传递Some(value)或None,或者至少调用value.into()。在某种程度上,API可以使用泛型来使这更方便(例如,fn function<T>(maybe_value: T) where T: Into<Option<SomeType>>会接受普通的value)。
一般来说,这会导致更多的面向类型的编程.与传递普通字符串不同,您更有可能看到将这些字符串解析为枚举或其他表示形式。在这里,代码使用ShaderSource枚举来清晰地表示各种变体。
斯威夫特的价值观完全不同。作为目标C的继承者,它在苹果生态系统中得到了广泛的应用。它本质上是建立在任何地方命名参数的思想之上的。它高度重视生产力。在某种程度上,这涉及到类似的面向类型的编程思想,但它不会为了性能而牺牲生产力。因此,String(contentsOfFile: ...)非常方便,在这种情况下很有意义,而Rust的include_str!()和std::fs::read_to_string()提供了更多的控制-例如,Rust宏将在编译时将文件内容包含到二进制文件中。
JavaScript是一种高度动态的语言,它不关心类型,也不关心如何安全地使用一种用于提前编译的语言来处理命名的参数。您无法合理地将JavaScript在foo({args})中使用对象与Rust的结构或Swift的命名参数进行比较,至少在考虑到每种语言的目标时是如此。
那么,你能做些什么来让你的生锈生活更能忍受呢?
use来导入或重命名它们。使用不多,宏可能是有用的。下面是我如何编写您的代码:
use wgpu::{ShaderModuleDescriptor, ShaderFlags, ShaderSource};
const SHADER_SOURCE: &str = include_str!("shader.wgsl");
let shader = device.create_shader_module(&ShaderModuleDescriptor {
label: Some("Shader"),
flags: ShaderFlags::all(),
source: ShaderSource::Wgsl(SHADER_SOURCE.into()),
});如果我写了很多这样的代码,我会考虑一个帮助函数…
fn create_shader_module(device: &Device, label: &str, source: impl Into<Cow<str>>) -> ShaderModule {
let source = ShaderSource::Wgsl(source.into());
device.create_shader_module(&ShaderModuleDescriptor {
label: Some(label),
flags: ShaderFlags::all(),
source,
})
}…或者创建更方便的类型别名,例如use wgpu::ShaderModuleDescriptor as SMD。
此外,如果要将struct组件提取到命名变量中,则可以使用与JS中相同的速记符号:
let label = ...;
let flags = ...;
let source = ...;
let shader = device.create_shader_module(&ShaderModuleDescriptor {
labels, flags, source,
});然而,这并不能使代码在一般情况下更简洁。
https://softwareengineering.stackexchange.com/questions/426863
复制相似问题