- 浏览: 3016063 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
今天写代码的时候不小心写错了几个地方,把同一个ParameterExpression用在内外两个Expression tree里了。结果很诡异,总之先记下来。
用LINQv1,测试这样的代码:
结果无论在内层的lambda里我输出x还是y,得到的都是5。于是我就纳闷了……
糟就糟在,这个lambda没办法用普通C#的lambda表达式写出来,因为如果这样写:
在C#里是不合法的:x和y在内层被重定义了,而C#不允许这样的重定义。
本来这个时候应该拿SOS来调试一下,看看到底Compile出了怎样的DynamicMethod。不过想着既然有IronPython的LINQv2,干脆拿源码来调试更方便。
于是引用IronPython里的Microsoft.Scripting.Core.dll,把测试代码改成:
就是换了俩namespace。在第29行设上断点,然后跟到LambdaExpression.Compile() -> LambdaCompiler.Compile() -> LambdaCompiler.CreateDelegate(),在这里看到底生成了怎样的DynamicMethod。
结果看到外层的DynamicMethod是:Void lambda_method$1(Microsoft.Runtime.CompilerServices.Closure, Double, Double)
其中调用的内层DynamicMethod是:Void lambda_method$2(Microsoft.Runtime.CompilerServices.Closure, Double, Double)
一看,这不就对了么?编译出来的应该跟这个lambda表达式的一样才对啊:
然后离开单步模式,直接运行下去,发现确实跟我原本预期的行为是一样的。把内层的x换成y也没错:内层是x的时候看到输出是5,内层是y的时候看到输出是2。
也就是说LINQv1和LINQv2中ParameterExpression的语义有了很大的变化,影响到了原本LINQv1中的Expression tree的语义……
那LINQv1到底是怎么回事呢?还真是得拿SOS来调试才行了,呜。回头再说吧。
用LINQv1,测试这样的代码:
using System; using Linq = System.Linq.Expressions; using Ast = System.Linq.Expressions.Expression; sealed class Program { static void Main(string[] args) { var x = Ast.Parameter(typeof(double), "x"); var y = Ast.Parameter(typeof(double), "y"); var expr = Ast.Lambda<Action<double, double>>( Ast.Invoke( Ast.Lambda<Action<double, double>>( Ast.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }), Ast.Convert( x, typeof(object) ) ), new [] { x, y } ), new Linq.Expression[] { y, x } ), new [] { x, y } ); expr.Compile()(2, 5); } }
结果无论在内层的lambda里我输出x还是y,得到的都是5。于是我就纳闷了……
糟就糟在,这个lambda没办法用普通C#的lambda表达式写出来,因为如果这样写:
Expression<Action<double, double>> expr = (x,y) => ((Action<double, double>)((x,y) => Console.WriteLine(x)))(y,x);
在C#里是不合法的:x和y在内层被重定义了,而C#不允许这样的重定义。
本来这个时候应该拿SOS来调试一下,看看到底Compile出了怎样的DynamicMethod。不过想着既然有IronPython的LINQv2,干脆拿源码来调试更方便。
于是引用IronPython里的Microsoft.Scripting.Core.dll,把测试代码改成:
using System; using Dlr = Microsoft.Linq.Expressions; using Ast = Microsoft.Linq.Expressions.Expression; sealed class Program { static void Main(string[] args) { var x = Ast.Parameter(typeof(double), "x"); var y = Ast.Parameter(typeof(double), "y"); var expr = Ast.Lambda<Action<double, double>>( Ast.Invoke( Ast.Lambda<Action<double, double>>( Ast.Call( null, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(object) }), Ast.Convert( x, typeof(object) ) ), new [] { x, y } ), new Dlr.Expression[] { y, x } ), new [] { x, y } ); expr.Compile()(2, 5); } }
就是换了俩namespace。在第29行设上断点,然后跟到LambdaExpression.Compile() -> LambdaCompiler.Compile() -> LambdaCompiler.CreateDelegate(),在这里看到底生成了怎样的DynamicMethod。
结果看到外层的DynamicMethod是:Void lambda_method$1(Microsoft.Runtime.CompilerServices.Closure, Double, Double)
IL_0000: /* 02 | */ ldarg.0 IL_0001: /* 7b | 04000002 */ ldfld !"指定的转换无效。"! IL_0006: /* 16 | */ ldc.i4.0 IL_0007: /* 9a | */ ldelem.ref IL_0008: /* 74 | 02000003 */ castclass System.Reflection.Emit.DynamicMethod IL_000d: /* d0 | 02000004 */ ldtoken Microsoft.Action`2[System.Double,System.Double]/ IL_0012: /* 28 | 06000005 */ call System.Type GetTypeFromHandle(System.RuntimeTypeHandle)/System.Type IL_0017: /* 14 | */ ldnull IL_0018: /* 6f | 06000006 */ callvirt System.Delegate CreateDelegate(System.Type, System.Object)/System.Reflection.Emit.DynamicMethod IL_001d: /* 74 | 02000007 */ castclass Microsoft.Action`2[System.Double,System.Double] IL_0022: /* 04 | */ ldarg.2 IL_0023: /* 03 | */ ldarg.1 IL_0024: /* 6f | 06000008 */ callvirt Void Invoke(Double, Double)/Microsoft.Action`2[System.Double,System.Double] IL_0029: /* 2a | */ ret
其中调用的内层DynamicMethod是:Void lambda_method$2(Microsoft.Runtime.CompilerServices.Closure, Double, Double)
IL_0000: /* 03 | */ ldarg.1 IL_0001: /* 8c | 02000002 */ box System.Double IL_0006: /* 28 | 06000003 */ call Void WriteLine(System.Object)/System.Console IL_000b: /* 2a | */ ret
一看,这不就对了么?编译出来的应该跟这个lambda表达式的一样才对啊:
Expression<Action<double, double>> expr = (x,y) => ((Action<double, double>)((m,n) => Console.WriteLine(m)))(y,x);
然后离开单步模式,直接运行下去,发现确实跟我原本预期的行为是一样的。把内层的x换成y也没错:内层是x的时候看到输出是5,内层是y的时候看到输出是2。
也就是说LINQv1和LINQv2中ParameterExpression的语义有了很大的变化,影响到了原本LINQv1中的Expression tree的语义……
那LINQv1到底是怎么回事呢?还真是得拿SOS来调试才行了,呜。回头再说吧。
发表评论
-
对象的重量
2011-08-21 17:15 0http://domino.research.ibm.com/ ... -
IronRuby 1.1系的自适应执行(解释/编译的混合模式)
2010-10-29 14:12 0IronRuby自身的compiler部分基本上还是保持不变的 ... -
Expression Tree中的Constant被编译后放到哪里去了?
2010-02-28 16:21 0Expression.Constant()可以放任意对象进去作 ... -
拿ETv2来生成方法体的两种阳春办法
2009-09-22 06:03 0System.Type System.Reflection.E ... -
C#的语言结构到Expression Tree v2的映射
2009-05-21 03:11 0在.NET Framework 4 Beta 1中,Expre ... -
.NET Framework 4.0 Beta 1里的Expression Tree一例
2009-05-20 10:23 2876既然装上了Visual Studio 20 ... -
用Iron-*语言来探索.NET
2009-05-15 23:21 3345刚才写代码的时候又是在不停查文档,甚是心烦。一怒,拿出Iron ... -
自己关于VM的帖的目录
2009-04-07 14:02 68799JavaEye的blog系统只允许把帖放到单一类别下,而不能用 ... -
MIX09上关于DLR解释器消息的一段听记(3月26更新IronPython 2.6A1消息)
2009-03-23 21:09 1799John Lam在MIX 09上做了一个关于动态语言与Silv ... -
答复: C# 4 DLR & Java 7 Invokedynamic
2009-03-22 17:12 2968原帖地址:C# 4 DLR & Java 7 Invo ... -
通过get或set方法的MethodInfo获得相应的PropertyInfo的方式
2009-02-01 22:41 3502在IronPython 46307的MemberExpress ... -
CodePlex上放出DLR v0.9 beta
2008-11-27 14:34 1940之前提到过DLR会在CodePlex上拥有自己独立的项目页面, ... -
IronRuby (r170)中respond_to?的实现
2008-11-13 23:29 0IronRuby.Libraries/Builtins/Ker ... -
DLR中的binder的演变
2008-11-11 23:29 0从模糊的“标准消息”转变为明确完整的MetaObject Pr ... -
DLR即将在Codelex开设独立的站点
2008-10-29 23:01 1406DLR官网:Dynamic Language Runtime ... -
IronPython放出RC1
2008-10-23 09:59 1788下载链接:http://www.codep ... -
新的DLR tree改变了Visitor的设计
2008-10-09 00:35 1582之前的一帖提到过访问DLR tree所使用的visitor的实 ... -
对比DLR
2008-10-08 04:32 0Managed JScript: // // AST: E ... -
目前DLR执行一棵DLR tree的过程(针对10月3日的ChangeSet 41087)
2008-10-07 01:46 1735先在Microsoft.Scripting.Actions.C ... -
LINQ与DLR的Expression tree(4):创建静态类型的LINQ表达式树节点
2008-09-27 00:18 9310(Disclaimer:如果需要转载请先与我联系;文中图片请不 ...
相关推荐
它由 Alonzo Church 和 Stephen Cole Kleene 在 20 世纪三十年代引入,Church 运用 lambda 演算在 1936 年给出 判定性问题 (Entscheidungsproblem) 的一个否定的答案。这种演算可以用来清晰地定义什么是一个可计算...
Lambda代码段实际为一个编译器生成的类的“operator ()”函数,编译器会为每一个Lambda函数生成一个匿名的类(在C++中,类和结构体实际一样,无本质区别,除了默认的访问控制)。 对Lambda的最简单理解,是将它...
城市就是森林,每一个男人都是猎手,每一个女人都是陷阱。——《三体》 在哪使用Lambda表达式? 在上一篇文章(传送门)中介绍了Lambda表达式的基本语法,其中的举了一个Lambda表达式的例子,就是按照品牌给口罩列表...
理解类的重要概念和相关知识,理解C#中高级类型(例如可空类型、泛型等),Lambda表达式和LINQ的原理和使用。 字段是与类或类的实例关联的变量。 使用 static 修饰符声明的字段定义了一个静态字段 (static field)...
Java 8 在 2013 年发布,Java 8 将支持 Lambda 功能,尽管该规范还在不断的变化,但是 Java 8 的开发版已经实现了对 lambda 的支持。
Python-lambda: 10分钟以内完成第一个 Python 的 Lambda 微应用-AWS Lambda 是种支持 Python/Jana/Node.js 的无主机应用发布平台. 只有在有请求时才真正运行的应用. 编写 Lambda 应用比较简单, 但是,绑定和部署没...
这段代码实现了一个简单的用户管理系统UserManager,其中使用了Java的Lambda表达式。在类的构造方法中,首先创建了一个空的用户列表users。然后实现了四个方法:addUser()用于添加用户,removeUser()用于删除用户,...
Lambda-toolkit 是一个lambda命令行(CLI)。 它可以帮助您在自己的机器中创建,构建,调试实际事件,测试和部署您的lambda功能。
在了解Lambda表达式之前我们先来区分一下面向对象的思想和函数式编程思想的区别 面向对象的思想: 做一件事情,找一个能解决这个事情的对象,调用他的方法来解决 函数时编程思想: 只要能获取到结果,谁去做的都不...
适用人群 本源码资源适用于具备一定Java编程基础的开发人员和学习者。...2、函数式接口与Lambda表达式:学习如何使用Lambda表达式与不同类型的函数式接口进行交互,并了解如何通过Lambda表达式实现函数的传递和组合
一个 lambda 演算的解释器实现
一个简单的Python库,使得旨在在Lambda中使用时,让Alexa技能发展变得容易
2_Lambda表达式.zip2_Lambda表达式.zip2_Lambda表达式.zip
在使用的时候 函数名(变量) eg. 通过常规方式定义函数 if x<y: res = x+y else: res = x-y return res print(fun(1,3)) # 4 通过lambda表达式定义一个函数 fun = lambda x, y: x+y if x<y else x-y ...
λ演算(lambda calculus)是一套用于研究函数定义、函数应用和递归的形式系统。它由阿隆佐·邱奇和他的学生斯蒂芬·科尔·克莱尼在20世纪30年代发明的。 λ演算可以被称为最小的通用程序设计语言。它包括一条变换...
learn-aws-lambda, 了解如何使用 AWS Lambda轻松创建无限可伸缩的Web服务 知识库 了解在 LESS 时间和成本范围内使用 AWS Lambda创建可以扩展的微型服务比基于服务器的应用程序运行的成本高 。 电子邮件内容什么是 ...
AWS DevOps 通过Config自动审计Security Group配置. ...这个实验的一个场景是,运维...(如果你了解一些Lambda就会非常清楚这个逻辑了)修改,添加或已有的Security —— 触发Config的审计—— 触发Lambda来修改正确的规则
讲解lambda在C#中的使用场景,及lambda的一些高级应用
java8lambda表达式的安卓Studio工程Demo,供初步学习使用
一个无缝的方式执行Go web应用程序在AWS Lambda和AWS API 网关