- 浏览: 3048271 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (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 2929既然装上了Visual Studio 20 ... -
用Iron-*语言来探索.NET
2009-05-15 23:21 3418刚才写代码的时候又是在不停查文档,甚是心烦。一怒,拿出Iron ... -
自己关于VM的帖的目录
2009-04-07 14:02 69504JavaEye的blog系统只允许把帖放到单一类别下,而不能用 ... -
MIX09上关于DLR解释器消息的一段听记(3月26更新IronPython 2.6A1消息)
2009-03-23 21:09 1857John Lam在MIX 09上做了一个关于动态语言与Silv ... -
答复: C# 4 DLR & Java 7 Invokedynamic
2009-03-22 17:12 3024原帖地址:C# 4 DLR & Java 7 Invo ... -
通过get或set方法的MethodInfo获得相应的PropertyInfo的方式
2009-02-01 22:41 3557在IronPython 46307的MemberExpress ... -
CodePlex上放出DLR v0.9 beta
2008-11-27 14:34 2016之前提到过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 1460DLR官网:Dynamic Language Runtime ... -
IronPython放出RC1
2008-10-23 09:59 1853下载链接:http://www.codep ... -
新的DLR tree改变了Visitor的设计
2008-10-09 00:35 1629之前的一帖提到过访问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 1806先在Microsoft.Scripting.Actions.C ... -
LINQ与DLR的Expression tree(4):创建静态类型的LINQ表达式树节点
2008-09-27 00:18 9378(Disclaimer:如果需要转载请先与我联系;文中图片请不 ...
相关推荐
在Python中,我们可以用相对简单的代码实现一个Lambda演算的解释器,来理解和操作这种抽象的计算系统。 ### Lambda表达式 Lambda演算的核心是lambda表达式,它由三部分组成:变量、箭头(λ)和函数体。一个简单的...
在Lambda演算中,一个重要的概念是能够用Lambda表达式来定义各种数学对象和运算。 ##### 4.1 Lambda可定义的自然数 自然数可以通过Church编码来表示。例如,数字0可以表示为一个接受一个参数但返回空函数的函数: ...
Lambda 表达式的定义仅仅是定义一个匿名方法,最终会生成一个委托对象。外部变量的引用将被“捕获”到委托对象内部,将会伴随委托对象的整个生命周期。 高级应用 Lambda 表达式可以用于数据查询、事件处理、线程池...
在Java 8中,Lambda表达式主要用于那些只包含一个抽象方法的接口,即功能接口。 在Java 8之前,我们常常需要使用匿名内部类来实现功能接口,这样做会生成很多冗余的代码。例如,添加一个事件监听器通常需要使用匿名...
Lambda表达式的主要目的是为了创建匿名函数,即没有名字的函数,它可以被当作一个值传递给方法或存储在变量中。在本资料"2_Lambda表达式.zip"中,我们可能将深入学习Lambda表达式的概念、语法以及在实际开发中的应用...
在编程领域,`lambda`表达式是一种简洁的创建匿名函数的方式,它允许我们在不定义完整函数的情况下使用函数。在Python中,`lambda`表达式特别常见,因为它们可以帮助我们快速编写简洁的一行函数。本文将深入探讨如何...
Lambda表达式是Java编程语言中的一个关键特性,它在Java 8中被引入,极大地简化了函数式编程。Lambda表达式本质上是匿名函数,可以被用作方法参数或局部变量,使得代码更加简洁且易于理解。这篇教程是针对初学者准备...
Lambda表达式本质上是一个匿名函数,允许你将函数作为一个值传递,这在处理函数式编程任务时尤其有用。下面我们将详细探讨Lambda表达式的核心概念、使用场景、对接口的要求以及函数式接口。 1. **Lambda表达式的...
Java 8 是一个重要的Java平台版本,因为它引入了许多新特性,其中最显著的就是Lambda表达式。Lambda表达式是函数式编程的关键元素,它允许我们以更简洁、更易读的方式编写代码,特别是在处理集合和并发任务时。在这...
在C++中,Lambda函数是一种特殊的匿名函数,它使得开发者能够在代码中的任何地方快速定义小块的代码,并将其作为参数传递,或直接作为函数调用。Lambda函数通常被用于需要函数对象的场景,比如在STL算法中。这种函数...
这里,Lambda表达式`(ch => ch == targetChar)`被传递给`FirstOrDefault`方法,该方法会在数组中查找满足条件的第一个元素。如果没有找到,`FirstOrDefault`会返回默认值(对于字符类型是'\0')。 Lambda表达式的...
Python-LambdaToolkit是一个专为Python开发者设计的命令行工具,它简化了AWS Lambda函数的开发、构建、调试、测试和部署流程。这个工具让开发者能够在本地环境中高效地操作Lambda函数,极大地提高了工作效率。 ### ...
方法引用是指 lambda 表达式允许我们定义一个匿名方法,并允许我们以函数式接口的方式使用它。函数式编程是指使用 lambda 表达式来实现业务功能,它可以将业务功能简洁的实现。 lambda 表达式的主要用途是替代匿名...
MATLAB版本的LAMBDA算法为用户提供了一个高效且易于使用的工具,包含了源码和详细的说明手册。 **一、LAMBDA算法的核心概念** 1. **模糊度**:在GPS测量中,相位观测值是浮点数,包含一个整数部分(模糊度)和一个...
这个语句Lambda接收一个参数`n`,并在控制台上打印一条消息。 4. **类型推断(Type Inference)** Lambda表达式中的类型通常不需要显式声明,编译器会根据上下文推断参数和返回值的类型。例如: ```csharp lst....
由于不同频率的电磁波在电离层中的传播速度不同,导致相位观测值存在差分相位,这个差分相位被称为电离层延迟的双频线性组合。通过计算这个组合,可以估算出一个模糊度因子,然后利用这个因子将浮点解转换为整数解,...
在上述示例中,`FuncInterface`也是一个自定义的函数式接口,包含一个抽象方法`abstractFun(int x)`和一个默认方法`normalFun()`。 3. **Lambda表达式的使用场景** - **作为方法参数**:例如,`arrL.forEach(n -> ...
在这个例子中,`(p1, p2) -> p1.getAge() - p2.getAge()` 就是一个Lambda表达式,它定义了一个比较两个Person对象年龄的方法。这里的`p1, p2`是参数,`->`后面是方法体,即计算两个Person的年龄差值。 Lambda表达式...
在这个"亚马逊AWS Lambda demo"中,我们将深入探讨如何使用Lambda构建一个简单的Maven项目。 首先,Lambda函数是AWS Lambda的核心组件,它是一小段可以响应特定事件的代码。在这个Maven demo中,我们可能有一个Java...
**C++ Lambda表达式**是C++编程语言中一个强大的特性,从C++11标准开始引入,到C++20标准进一步增强。Lambda表达式允许程序员在代码中定义匿名函数,即没有名称的函数,这极大地提高了代码的灵活性和可读性。本书...