Lambda 是在函数/方法中创建可重用代码而不污染父类的绝佳方式。大多数情况下,它们是 C 风格宏的功能性替代品。
然而,宏中有一点语法糖,我似乎无法用 lambda 复制,那就是从包含函数中退出的能力。例如,如果我需要在检查一系列ints的范围时返回,我可以使用宏轻松完成:
const int xmin(1), xmax(5);
#define CHECK_RANGE(x) { if((x) < xmin || (x) > xmax) return false; }
bool myFunc(int myint) {
CHECK_RANGE(myint);
int anotherint = myint + 2;
CHECK_RANGE(anotherint);
return true;
}
Run Code Online (Sandbox Code Playgroud)
显然这是一个过于简化的例子,但基本前提是我对不同的变量一遍又一遍地执行相同的检查,我认为封装检查和相关出口更具可读性。不过,我知道宏不是很安全,尤其是当它们变得非常复杂时。但是,据我所知,尝试执行等效的 lambda 需要像这样的笨拙的额外检查:
const int xmin(1), xmax(5);
auto check_range = [&](int x) -> bool { return !(x < xmin || x > xmax); };
bool myFunc(int myint) {
if(!check_range(myint)) return false;
int anotherint = myint + 2; …Run Code Online (Sandbox Code Playgroud) 我正在学习 Scala 并发现以下内容:
List(('a', 1)).toMap get 'a' // Option[Int] = Some(1)
(List(('a', 1)).toMap) apply 'a' // Int = 1
(List(('a', 1)).toMap)('a') // Error: type mismatch;
found : Char('a')
required: <:<[(Char, Int),(?, ?)
(List(('a', 1)).toMap)('a')
Run Code Online (Sandbox Code Playgroud)
但是然后将其分配给变量再次起作用。
val b = (List(('a', 1)).toMap)
b('a') // Int = 1
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
标准文档给出:
ms get k与映射 ms 中的键 k 关联的值作为选项,如果未找到则为 None。
ms(k)(或,写出,ms apply k)与映射 ms 中的键 k 关联的值,如果未找到则为异常。
为什么第三行不起作用?
这是受到我给新手用户的回答的启发,我建议他们使用 anstd::variant而不是 union。
通过工会,您可能会遇到如下情况:
struct Box {
struct Item { float value; };
using Boxes = std::vector<Box>;
union Value {
Item item;
Boxes boxes;
};
Value contents;
std::string label;
};
Run Code Online (Sandbox Code Playgroud)
(不完全是最初的问题,我在这里接受了一些诗意的许可。)并且使用一个变体,该类可能如下所示:
struct Box {
struct Item { float value; };
using Boxes = std::vector<Box>;
std::variant<Item, Boxes> contents;
std::string label;
};
Run Code Online (Sandbox Code Playgroud)
问题是,使用第一个变体,我可以写
if (box.contents.boxes.size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)
如果我已经确定会有子框,这就会起作用。
对于std::variant,我必须写:
if (std::get<Boxes>(box.contents).size() > 2) { foo(); }
Run Code Online (Sandbox Code Playgroud)
我觉得第二个版本的可读性要差得多,有点混乱,而且很分散注意力。另外 - 我必须知道 的类型boxes。
在我的代码中,我可以做些什么来让我的用户无需进行此类std::get()调用,并使他们的生活更加愉快?
如果我有一个需要Default实现的结构,如果所有字段的类型都Default实现了它们,那么我可以使用derive宏,否则我需要Default手动实现。但是,在某些情况下,我有一个大型结构,其中几乎所有字段都是可导出的,除了少数字段的类型尚未实现Default,而且我impl自己可以,因为类型是外部的。最终出现以下示例中的情况。我宁愿避免这种情况,因为这意味着我需要保持两个地方之间的字段同步,这更耗时、容易出错且冗长。我希望可能有一些语法方法可以避免这种情况,但我对 rust 很陌生,想不出任何方法。我在想这样的事情:
impl Default for Data2 {
fn default() -> Self {
Self {
external_data: ExternalType::One,
..Default::default(),
}
}
}
Run Code Online (Sandbox Code Playgroud)
例子
#[derive(Default)]
struct Data {
name: Option<String>,
flag: bool,
selected: Vec<String>,
show_reference: Option<String>,
index: Option<usize>,
create_name: String,
create_type: String,
}
enum ExternalType {
One,
Two,
}
// #[derive(Default)]
struct Data2 {
name: Option<String>,
flag: bool,
selected: Vec<String>,
show_reference: Option<String>,
index: Option<usize>,
create_name: String,
create_type: String,
external_data: ExternalType, …Run Code Online (Sandbox Code Playgroud) 我有一个包含向量的类:
class Foo {
typdef std::vector<int> Vec;
Vec m_kids;
void addKids(Vec::const_iterator begin,
Vec::const_iterator end) {
m_kids.insert(m_kids.end(), begin, end);
}
};
Run Code Online (Sandbox Code Playgroud)
有没有办法允许以下简洁的函数调用?(也许通过改变addKids上面的功能?)
int main() {
Foo foo;
foo.addKids(23,51,681); // these...
foo.addKids(3,6,1,4,88,2,4,-2,101); // ...would be nice?!
}
Run Code Online (Sandbox Code Playgroud)
我怀疑你可以使用C++ 0x向量初始化列表吗?但不幸的是,我无法使用C++ 0x.不过,如果有帮助,我可以使用Boost.
假设我们想尝试将null赋给某个东西,我们想要抛出,这个技巧怎么样:
public static class ExceptionExtension
{
public static T Throw<T>(this Exception exc)
{
throw exc;
}
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用这样的例子:
return possibleNull ?? new Exception("Unspecified something....").Throw<string>();
Run Code Online (Sandbox Code Playgroud)
你认为这是一个好/坏/没用的做法吗?
任务是翻译这个
f = do
c <- [1 .. 200]
b <- [1 .. 200]
guard (c >= b)
a <- [1 .. 200]
guard (a >= b && (c^2 - a^2 == b^2))
return (a,b, c)
Run Code Online (Sandbox Code Playgroud)
成为一个非糖的版本.
我想我已经弄清楚了大部分问题,但是我在中间遇到了一个我需要修复的问题才能继续.到目前为止,我有:
f = [1 .. 200] >>= \c ->
[1 .. 200] >>= \b ->
if (c >= b)
then [1 .. 200] >>= \a -> if (a >= b && (c^2 - a^2 == b^2))
then return(a,b,c)
else return ()
else return …Run Code Online (Sandbox Code Playgroud) 我花了这么多时间在我的伴侣对象中组合一个工厂方法,如下所示:
class Stuff(val a: Int, val b: Long) { this() = this(0,0L) }
object Stuff {
def apply(a:Int, b:Int) = new Stuff(a, b.toLong)
}
Run Code Online (Sandbox Code Playgroud)
但是,当我以为我杀了它时,我就去编译,这不起作用:
val widget = new Stuff(1,2)
Run Code Online (Sandbox Code Playgroud)
到底是怎么回事!?我刚做完了!?救命!!!
在重构一些代码时,我经常会遇到这样的问题:
bool highLevelFunc foo()
{
// ...
bool result = LesserLevelFunc();
if (!result) return false;
// ... Keep having fun if we didn't return
}
Run Code Online (Sandbox Code Playgroud)
有没有办法让这个更性感,更简洁?当然没有任何开销或陷阱.
我能想到一个宏
#define FORWARD_IF_FALSE(r) if (!r) return r;
bool highLevelFunc foo()
{
// ...
FORWARD_IF_FALSE(LesserLevelFunc());
// ...
}
Run Code Online (Sandbox Code Playgroud)
有什么更好的,即没有预处理器宏?
我可以apply在Scala 中使用来重载()运算符.
class A {
val arr = Array[Int](1,2,3,4,5)
def apply(i:Int) = {
arr(i)
}
}
object Main extends App {
val a = new A
println(a(0))
}
Run Code Online (Sandbox Code Playgroud)
当我设置值时,我可以添加set方法
def set(i:Int, value:Int) = {arr(i) = value}
...
arr.set(3, 10)
Run Code Online (Sandbox Code Playgroud)
Scala是否允许更好的语法糖,例如arr(3) = 10获得相同的结果?