使用新的 C# 7 元组语法,是否可以指定一个以元组作为参数的 lambda 并在 lambda 中使用未打包的值?
例子:
var list = new List<(int,int)>();
在 lambda 中使用元组的正常方法:
list.Select(value => value.Item1*2 + value.Item2/2);
我期待一些新的糖来避免 .Item1 .Item2,比如:
list.Select((x,y) => x*2 + y/2);
最后一行不起作用,因为它被视为 lambda 的两个参数。我不确定实际上是否有办法做到这一点。
编辑:
我在 lambda 定义中尝试了双括号但它不起作用:((x,y)) => ...,也许尝试是愚蠢的,但双括号确实有效这里:
list.Add((1,2));
另外,我的问题不完全是关于避免难看的默认名称 .Item .Item2,而是关于在 lambda 中实际解包一个元组(以及为什么它没有实现或不可能)。如果您是来这里寻找默认名称的解决方案,请阅读 Sergey Berezovskiy's answer .
编辑 2:
只是想到一个更一般的用例:是否有可能(或为什么不)“解构”传递给方法的元组?像这样:
void Foo((int,int)(x,y)) { x+y; }
取而代之的是:
void Foo((int x,int y) value) { value.x+value.y }
最佳答案
正如您所观察到的,对于:
var list = new List<(int,int)>();
人们至少希望能够做到以下几点:
list.Select((x,y) => x*2 + y/2);
但 C# 7 编译器(目前)还不支持这一点。期望允许以下情况的糖也是合理的:
void Foo(int x, int y) => ...
Foo(list[0]);
编译器将 Foo(list[0]); 自动转换为 Foo(list[0].Item1, list[0].Item2);。
目前这些都不可能。然而,这个问题,Proposal: Tuple deconstruction in lambda argument list ,存在于 GitHub 上的 dotnet/csharplang 存储库中,要求语言团队在未来的 C# 版本中考虑这些功能。如果您也希望看到对此的支持,请将您的声音添加到该线程。
关于C# 7 元组和 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43082026/
我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject
这段代码没有像我预期的那样执行:casewhen->{false}then"why?"else"ThisiswhatIexpect"end#=>"why?"这也不是casewhen->(x){false}then"why?"else"ThisiswhatIexpect"end#=>"why?"第一个then子句在两种情况下都被执行,这意味着我提供给when子句的lambda没有被调用。我知道无论when子句的主题是什么,都应该调用大小写相等运算符===。我想知道当没有为case提供参数时,===的另一边会发生什么。我在想它可能是nil,但它不可能是:->{false}===nil#=>
如何将lambda传递给hash.each,以便我可以重复使用一些代码?>h={a:'b'}>h.eachdo|key,value|end=>{:a=>"b"}>test=lambdado|key,value|puts"#{key}=#{value}"end>test.call('a','b')a=b>h.each&testArgumentError:wrongnumberofarguments(1for2)from(irb):1:in`blockinirb_binding'from(irb):5:in`each'from(irb):5from/Users/jstillwell/.rv
是否可以不为lambda分配上下文?例如:classRuledefget_rulereturnlambda{putsname}endendclassPersonattr_accessor:namedefinit_rule@name="ruby"Rule.new.get_rule.call()#shouldsay"ruby"butsaywhatobjectofclassRull,doesnothavevariablename#orself.instance_eval&Rule.new.get_ruleendend我的目标是->没有上下文的存储过程对象,并在特定位置调用之前分配上下文。可能
要清楚-此代码运行完美-codewithproc但如果我将Proc.new更改为lambda,则会出现错误ArgumentError:wrongnumberofarguments(1for0)这可能是因为instance_eval想要将self作为参数传递,而lambda将其视为一种方法并且不接受未知参数?有两个例子-第一个是工作:classRuledefget_ruleProc.new{putsname}endendclassPersonattr_accessor:namedefinit_rule@name="ruby"instance_eval(&Rule.new.get_rule
我很难理解是什么使以下行为成为可能(摘自ruby镐书):defpower_proc_generatorvalue=1lambda{value+=value}endpower_proc=power_proc_generator3.times{putspower_proc.call}#=>2,4,83.times{putspower_proc_generator.call()}#=>2,2,2我没有看到“power_proc”对象如何允许值继续加倍,因为我假设(似乎是错误的)每次调用都会将值重新分配给1。我的问题是为什么“3.times{putspower_proc.call}”的结果是“
loop{break}可以正常工作,但是block=Proc.new{break}#or#block=lambda{break}loop(&block)#=>LocalJumpError:breakfromproc-closure是否可以在block变量中中断?更新:举例说明:defodd_loopi=1loopdoyieldii+=2endenddefeven_loopi=2loopdoyieldii+=2endend#Thisworkodd_loopdo|i|putsibreakifi>10end#Thisdoesn'tworkbreak_greater_10=Proc.newdo
如下面的ruby示例所示,我无法调用参数数量错误的lambda作为从Method创建的Proc因为它对参数的数量很严格:#methodwithnoargsdefa;endinstance_eval(&method(:a))#ArgumentError:wrongnumberofarguments(1for0)method(:a).to_proc.call(1,2,3)#ArgumentError:wrongnumberofarguments(3for0)method(:a).to_proc.lambda?#=>true如何从Proc或Method中获取不是lambda的Proc?
为什么带有splat参数的Ruby(2.0)过程/block的行为与方法和lambda不同?deffoo(ids,*args)pidsendfoo([1,2,3])#=>[1,2,3]bar=lambdado|ids,*args|pidsendbar.call([1,2,3])#=>[1,2,3]baz=procdo|ids,*args|pidsendbaz.call([1,2,3])#=>1defqux(ids,*args)yieldids,*argsendqux([1,2,3]){|ids,*args|pids}#=>1这是对此行为的确认,但没有解释:http://makandra
假设底层数据库支持,ActiveRecord是否支持where子句中的元组?生成的where子句类似于:where(name,address)in(('John','123MainSt'))我试过:Person.where({[:name,:address]=>['John','123MainSt']})但它没有用。 最佳答案 tupleArray=[['John','123MainSt'],['Jane','124MainSt']]Person.where("(name,address)IN(#{(['(?)']*tupleArr