1Swift相对与OC一些更好用的特性
(1)更好用的switchcase,for循环,枚举,结构体
a switchcase
不需要break,一个case可以写多个条件,使用fallthrough继续执行
基本数据类型都能判断,并且能使用where语句
b for循环
普通for循环
集合类型的遍历
c 枚举
d 结构体
结构体在Swift中的地位很重要,Array Dictionary Set Int Float Double Bool String都是结构体
(2)String与NSString
(3)函数
(4)可选项,安全的语言
(5)各种各样的基类
NSObject(OC中所有的类都是继承NSObject) < AnyObject(Swift中的类可以不继承任何类) < Any(包含了函数的类型)
(6)基本数据类型都是值类型,copy - on - write
2Swift的动态性
(0)大纲
a 纯Swift的类和继承自NSObject的类通过runtimeAPI获取方法属性
b @objc之后可以被runtimeAPI获取到,但是方法无法被替换
c dynamic后方法动态调用,可以被替换
d Swift和OC相互调用,Swift在OC类中的名字
e Swift使用关联对象
f Swift50方法交换,动态访问属性(动态传递参数,动态调用方法)
(1)使用runtime API与Swift
a @objc本意是让OC可以调用Swift的方法,@objc所修饰的属性,方法不能包含Swift特有的类
b @objc 信息能使用runtime获取,dynamic动态调用
c 如果类继承自Object-c的类会自动被编译器插入@objc标识
a 纯 Swift 类没有动态性,但在方法、属性前添加 dynamic 修饰可以获得动态性。
b 继承自 NSObject 的 Swift 类,其继承自父类的方法具有动态性,其他自定义方法、属性需要加 dynamic 修饰才可以获得动态性。
c 若方法的参数、属性类型为 Swift 特有、无法映射到 Objective-C 的类型 (如 Character、Tuple),则此方法、属性无法添加 dynamic 修饰(会编译错误)
d Swift 类在 Objective-C 中会有模块前缀
e 仍然可以使用关联对象技术
(2)Swift5的“Method Swizzling”
在路由router里面,每一个<Route>标签内的component属性可以是dynamic({xxx})返回的对象。
然后直接把路由挂在dva生成的app对象下就好了
<dynamic>元素划分出SQL语句的动态部分。动态部分可以包含任意多的条件标签元素,条件标签决定是否在语句中包含其中的SQL代码。所有的条件标签元素将根据传给动态查询Statement的参数对象的情况来工作。<dynamic>元素和条件元素都有“prepend”属性,它是动态SQL代码的一部分,在必要情况下,可以被父元素的“prepend”属性覆盖。上面的例子中,prepend属性“where”将覆盖第一个为“真”的条件元素。这对于确保生成正确的SQL语句是有必要的。例如,在第一个为“真”的条件元素中,“AND”是不需要的,事实上,加上它肯定会出错。以下小节讨论不同的条件元素,包括二元条件元素,一元条件元素和其他动态元素。
本文是滴滴发在KDD2020的paper。
文中指出用户响应预测的困难在于模型需要考虑真实物理环境中的历史信息和实时事件信息。
本文提出了使用动态构建的异构图来编码事件的属性和事件发生的周围环境。除此之外,文中提出了一种多层图神经网络模型来学习历史行为和周围环境对于当前事件的影响,生成有效的事件表示来改善相应模型的准确性。
首先文中定义了几个术语:PreView, Request, Cancel_Order, Finish_Order
PreView指的是用户确定起点和终点,页面上会显示出路线,服务类型,估计价格。Request指的是用户点击按钮,触发打车事件。Cancel_Order指的是司机到达前用户取消订单。Finish_Order指的是司机将用户送到目的地,用户付钱,完成整个交易流程。
本文的目标是对PreView事件建模,估计用户点击Request按钮的概率。
上图表示一个用户的打车流程。
文中使用名词POI(Point Of Interest)来表示地图上所有可能的上车和下车点。如上图所示,不同的用户行为同时发生在各个不同的POIs
用户是否会点击Request按钮会由很多因素来决定。一些因素是显式的,可以直接从数据源中获取,比如用户当前位置和上车点位置的距离,天气,时间等;一些因素是隐式的,比如用户对于等待的意愿,用户对于这笔花销的意愿,用户对于路线的满意程度等等,这些特征很难直接获取。
一种解决方案是从历史数据和当前时间的观测中引入一些代替的特征,比如用户行为历史中和交易相关的行为,当前实时物理环境中发生的一些事件等等。
比如用户在当前PreView之前可能已经完成了多个订单,我们可以使用这些历史信息来捕捉用户的潜在特征,比如用户对于服务类型的偏好,用户对于花销的意愿程度等等。
具体的,用户更倾向于对那些和之前已经完成的PreView类似的PreView发起Request。同样的,我们也可以从用户没有完成的PreView中来抽取负特征。
为了计算PreView之间的相似性,文中提出使用从历史数据中学习到的embedding。除此之外,我们希望embedding能够捕捉当时周围环境的供求情况。为了达到这一目的,文中提出利用周边地区同时发生的一些事件。比如周边地区有许多需求没有被满足,那么当前的供求关系是不平衡的。再比如周边地区有许多取消订单,那么路况可能是拥挤的,或者期望等待时间很长。由此可见,一些历史数据和当前正在发生的实时数据都能为预测模型提供信息。
然而,历史数据和实时数据对于当前分析事件的相关程度是不同的,因此引入异构图来表示这些关系。
在动态异构图中embed实时事件的挑战在于:
1)对于每个新发生的事件,需要对于这个时间动态构建一个图,包括收集相关乘客的历史事件,以及周边区域发生的事件。
2)图中的实体和关系是异构的。比如时间有PreView,Request等,事件之间的关系有相同的乘客,相同的起点等。
3)对于我们关注的事件,不同的实体和不同的关系的影响的重要性程度也是不同的。
4)对于大规模实时事件进行建模。
文中并没有采用在训练阶段embed item的做法,而是提出了一种新的框架来实时生成事件的表示,使得能够捕捉用户行为和周围环境的动态变化。
每个实体的embedding以一种基于GNN的inductive的方式生成。(实体包括事件,物品,用户行为等)
整个方法主要包括以下几个步骤:
1)为每个事件构建一个动态异构图。
2)使用文中提出的异构图embedding算法来生成事件的embedding。
3)基于实体的embedding进行实时预测。
文中提出了一个概念叫heterogeneous session(h-session)。比如在一次打车的行为过程中,在PreView事件之后,可能会有Request, Finish_Order, Cancel_Order等,这些事件就属于一个h-session,描述了用户一次完整的打车行为。
构建完异构图后,文中提出了一种新的图学习算法REGNN(Real-time Event Graph Neural Network)来生成事件的embedding。
对于每个需要预测的实时事件,动态创建一个异构图,图中包括了相关h-session中的事件和其他相关的实体。图中的边表示了节点之间各种复杂的关系,包括时间顺序上的关系,空间位置的关系,以及其他的逻辑关系。
上图记录了文中用到的一些符号表示。
定义图G=(VG,EG,OV,RE),节点映射函数VG->OV,边映射函数EG->RE,VG中的每个节点对应OV中的一种类型,EG中的每条边对应RE中的一种类型。当|OV|=1并且|RE|=1时,图为同构图;否则,图为异构图。
问题定义,PreView Conversion Prediction
given PreView事件 PT = (p,o,d,T), T表示时间,o表示起点,d表示终点,p表示用户。目标是估计用户p触发事件Request的概率yT,通过embedding一系列历史的动态异构图[G_PT, G_PT-1,, G_PT-N+1],G_Pt表示事件Pt的动态异构图,t=T-N+1,,T
G_P中包含了不同类型的事件和物品,embedding模型的目标是学习一个函数
给出一个时间序列信息和(1)中获得的embedding,上层模型的目标是学习一个模型Gθ,其中θ是参数来预测yT。
T为timestamp,Et表示时间t事件的embedding,N表示时间序列的长度。
首先介绍real-time event embedding框架。
考虑对于PreView最相关的属性:乘客,时间戳,起点,终点。
从乘客的角度,可以从其历史行为事件中获得信息。从起点和终点的角度,可以通过综合这两个地点的事件信息获得空间的表示。
整个工作流图如上所示。
•given PreView事件PT=(p,o,d,T),根据下面的流程生成异构图:
1)乘客视角:挑选乘客一周内在时间T之前最近的Np个PreView事件(包括Request, Finish_Order, Cancel_Order)。对于这些事件在图中创建相关的邻居节点,关于乘客p的这个子图记为HetGp,T。
2)起点和终点视角:在同时发生的PreView事件中,挑选在时间戳T之前x分钟内的和PT相同起点的PreView事件,包括它们相关的Request, FInish_Order, Cancel_Order事件。这些事件添加到图中作为起点子图HetGo,T另一方面,以相同的方式构建终点子图HetGd,T
3)为了整合历史PreViews的时空信息,用RNN学习历史事件序列的hidden state,以键值对的方式存储它们。因此,事件序列的下一个序列能够快速的预测和更新。
•根据这些事件和当前事件PT之间的关系,添加相关类型的边。比如属于同一个h-session这种关系,或者是各自属于的h-session之前有序列关系等。
•在构造的异构子图上,使用REGNN来生成PT的实时事件embedding。
•最后,生成的事件embedding作为下游预测任务的输入。
上图展示了PreView模型的具体细节。最下面三层是三个GAT,分别对应不同的粒度(GAT within h-session, GAT across h-sessions within the same subgraph, GAT across subgraphs),之后接GRU层,接MLP层,最后给出预测。
PT的动态异构图G_PT由三种子图组成
分别表示乘客子图,起点子图和终点子图。+表示图的join *** 作,定义为G=G1+G2, G1=(V1,E1), G2=(V2,E2),那么G的节点为V1∪V2,G的边为E1∪E2
三个子图的构建过程如下:
•inside h-session连接同一session中的事件来构建子图。
•across h-session为了分析前面的h-session对于目标PreView的影响,添加前面h-session到目标PreView之间的边。然而,不同的h-session起到的影响效果是不同的,因此边的类型也是不同的,
PT表示在时间T的PreView,使用最近的N个h-session来构建关于PT的图。
对于三种level,使用了三种不同的embedding模型。
•GATs inside h-session
上式中○+符号表示concatenate,OV表示一个h-session中不同类型的事件,K表示heads的总数(GAT中的head,即一条边上做几次attention)。h(1)h_s表示做一次GAT之后h-session的隐状态,h(0)h_s表示h-session的初始状态,用PreView事件的节点特征进行初始化。(P,R,F,C分别代表PreView,Request,finish,cancel)
•GATs across h-session
在不同的h-session之间执行attention *** 作。对于不同子图中的h-session,GAT如下
Np,No,Nd分别表示乘客子图,起点子图,终点子图中不同的时间戳的总数。
需要注意的是t从0开始,即加上了self attention
GATp的 *** 作如下,GATo和GATd类似。
各符号的意义和前面类似。
•GATs across subgraphs
最终综合三个子图,计算最后的embedding。
具体式子如下,
OG表示不同类型的异构子图。其余符号和前面的类似。
利用RNN对用户过去的PreView之间的时序依赖建模。文中使用了GRU
ET是在时间T进行global attention得到的最终embedding,也就是(7)中的hgPT
最终的损失函数
属性
“属性”是OC语法的特性,用于封装对象中的数据,每个不同的属性使用存取方法来调用,同样也可以使用点语法来更方便的 *** 作属性,例如
如果想在m文件中改变变量的名字,可以使用关键字synthesize
@synthesize name = _newName;
属性可以动态创建setter和getter方法,正常只能对其中一个方法进行重写,如果想要两个都重写使用dynamic
@dynamic name;
这里表示告诉编译器不需要自动合成setter和getter方法,当出现dynamic关键字的时候,即使没有重写存取方法,也不会报错
编译器会认为运行时可以找到该方法
属性特质
每个属性都有自己的属性特质,不同特质在系统自动生成setter和getter方法的时候也有着不同。
属性特质分为四大类
1原子性:atomic原子性,使用同步锁,安全性更高但是效率会降低,nonatomic非原子性,默认为atomic
2读/写权限:readwrite可读写,readonly只读,默认为readwrite
3内存管理语义:assign,对基本类型使用,strong强指针关系,weak弱指针关系,copy拷贝关系
4方法名:getter=<name> 或 setter=<name> 后者不常见 @property (nonatomic, getter=isOn) BOOL on;
本文部分内容参考自《effective+objective-c》一书,有兴趣的可以翻看一下
近几年来 在TIOBE公司每个月发布的编程语言排行榜[ ]中 总是能挤进前 名 而在近 年的编程语言排行榜中 C#总体上呈现上升的趋势 C#能取得这样的成绩 有很多因素在起作用 其中 它在语言特性上的锐意进取让人印象深刻(图 )
图 C#各版本的创新点
年发布的C# 最大的创新点是拥有了动态编程语言的特性
动态编程语言的中兴
动态编程语言并非什么新鲜事物 早在面向对象编程语言成为主流之前 人们就已经使用动态编程语言来开发了 即使在 C# 等面向对象编程语言繁荣兴旺 大行于世的年代 动态编程语言也在 悄悄 地攻城掠地 占据了相当的开发领域 比如 业已成为客户端事实上的主流语言
最近这几年 动态编程语言变得日益流行 比如Python Ruby都非常活跃 使用者众多
这里有一个问题 为什么我们需要在开发中应用动态编程语言?与C#和Java这类已经非常成熟且功能强大的静态类型编程语言相比 动态编程语言有何优势?
简单地说 使用动态编程语言开发拥有以下的特性
( )支持REPL(Read evaluate print Loop 读入à执行à输出 循环迭代)的开发模式 整个过程简洁明了 直指问题的核心
举个简单的例子 图 所示为使用IronPython[ ]编程计算 + +……+ 的屏幕截图 我们可以快速地输入一段完成累加求和的代码 然后马上就可以看到结果
图 使用IronPython编程
如果使用开发就麻烦多了 您得先用Visual Studio创建一个项目 然后向其中添加一个类 在类中写一个方法完成求和的功能 再编写调用这一方法的代码 编译 排错 最后才能得到所需的结果……
很明显 对于那些短小的工作任务而言 动态编程语言所具备的这种REPL开发模式具有很大的吸引力
( )扩展方便 用户可以随时对代码进行调整 需要什么功能直接往动态对象上 加 就是了 不要时又可以移除它们 而且这种修改可以马上生效 并不需要像C#那样必须先修改类型的定义和声明 编译之后新方法才可用
换句话说 使用动态语言编程 不需要 重量级 的OOAD 整个开发过程迭代迅速而从不拖泥带水
( )动态编程语言的类型解析是在运行时完成的 可以省去许多不必要的类型转换代码 因此 与静态编程语相比 动态编程语言写的代码往往更紧凑 量更少
动态编程语言主要的弱点有两个
( )代码中的许多错误要等到运行时才能发现 而且需要特定的运行环境支持 对其进行测试不太方便 也不支持许多用于提升代码质量的各种工具 因此不太适合于开发规模较大的 包容复杂处理逻辑的应用系统
( )与静态编程语言相比 动态编程语言编写的程序性能较低 不过随着计算机软技术的不断进步 比如多核的广泛应用 动态编程语言引擎和运行环境不断地优化 动态编程语言编写的程序性能在不断地提升 在特定的应用场景下 甚至可以逼近静态语言编写的程序
拥抱 动态编程 特性的
为了让C# Visual Basic等编程语言能具备动态编程语言的特性 NET 引入了一个 DLR(Dynamic Language Runtime 动态语言运行时) (图 )
图 DLR 动态语言运行时
DLR运行于CLR之上 提供了一个动态语言的运行环境 从而允许Python Ruby等动态语言编写的程序在 NET平台上运行 同时 现有的 NET静态类型编程语言 比如C#和Visual Basic 也可以利用DLR而拥有一些动态编程语言的特性
( )使用C# 编写动态的代码
C# 新增了一个dynamic关键字 可以用它来编写 动态 的代码
例如 以下代码创建了一个ExpandoObject对象(注意必须定义为dynamic)
dynamic dynamicObj = new ExpandoObject();
这一对象的奇特之处在于 我们可以随时给它增加新成员
dynamicObj Value = ; //添加字段dynamicObj Increment = new Action(() => dynamicObj Value++); //添加方法
这些动态添加的成员与普通的类成员用法一样
for (int i = ; i < ; i++)dynamicObj Increment();//调用方法Console WriteLine( dynamicObj Value={ } dynamicObj Value);//访问字段
ExpandoObject对象实现了IDictionary<string object>接口 可看成是一个字典对象 所有动态添加的成员都是这个字典对象中的元素 这意味我们不仅可以添加新成员 还可以随时移除不再需要的成员
//移除Increment方法(dynamicObj as IDictionary<stringobject>) Remove( Increment );
方法移除之后 再尝试访问此方法将引发RuntimeBinderException异常
( )使用dynamic关键字简化与组件交互的代码
要在这个 托管世界 里调用 非托管世界 中的组件 我们必须通过 互 *** 作程序集(Interop Assembly) 作为桥梁 互 *** 作程序集 定义了CLR类型与类型之间的对应关系
只要给 NET项目添加对 互 *** 作程序集 的引用 就可以在 NET应用程序中创建这一程序集所包容的各种类型的实例(即包装器对象) 对这些对象的方法调用(或对其属性的存取)将会被转发给组件
以调用Word为例 在 之前您可能经常需要编写这样的代码
Object wordapp = new Word Application(); //创建Word对象Object fileName = MyDoc docx;//指定Word文档Object argu = System Reflection Missing Value;Word Document doc = wordapp Documents Open(ref fileNameref arguref arguref arguref arguref arguref arguref argu ref arguref arguref arguref arguref arguref arguref arguref argu);
上述对Open()方法的调用语句只能用 恐怖 一词来形容 其原因是Word组件中的Open()方法定义了太多的参数
使用dynamic关键字 配合从Visual Basic中学来的 命名参数与可选参数 这两个新语法特性 可以写出更简洁的代码
dynamic wordapp = new Word Application();dynamic doc = wordapp Documents Open(FileName: MyDoc docx );
上述代码中省去了用不着的参数 并且可以去掉参数前的ref关键字
当上述代码运行时 DLR会使用反射技术将dynamic表达式 绑定(bind) 到互 *** 作程序集中所包容的Word Application代理对象
( )C# 动态编程技术内幕
C# 中所定义的dynamic变量可以引用以下类型的对象
l 传统的 静态 的CLR对象
l 包装器对象 前面已经介绍了这方面的内容
l 实现了IDynamicMetaObjectProvider接口的 动态对象 ExpandoObject就是这种类型对象的实例
l 基于DLR实现的动态语言(比如IronRuby和IronPython)所创建的对象
从程序员角度来看 所有这四种对象都是一样的 都可用一个dynamic变量引用之 而DLR在程序运行时动态地将方法调用和字段存取请求 绑定 到真正的对象上
dynamic的功能是由DLR所支撑的 是C#编译器与DLR分工合作的成果
请看以下示例代码
dynamic d = ;d++;
C#编译器在处理上述代码时 它并不去检查变量d是否可以支持自增 *** 作 而是为其创建了一个CallSite<T>对象(<>p__Site )
private static class <Main>o__SiteContainer{public static CallSite<Func<CallSiteobjectobject>> <>p__Site ;}
中文MSDN将CallSite<T>译为 动态(调用)站点 它是DLR中的核心组件之一
动态站点对象通过CallSite<T> Create()方法创建 C#编译器会为其指定一个派生自CallSiteBinder的对象(称为 动态站点绑定对象 )作为其参数
动态站点绑定对象是与具体语言相关的 比如IronPython和C#都有各自的动态站点绑定对象
动态站点绑定对象的主要工作是将代码中的动态表达式(本例中为d++)转换为一棵 抽象语法树(AST Abstract Syntax Tree) 这棵语法树被称为 DLR Tree 是在 所引入的LINQ表达式树的基础上扩充而来的 因此 有时又称其为 表达式树(Expression Tree)
DLR在内部调用此表达式树的Compile()方法生成IL指令 得到一个可以被CLR所执行的委托(在本例中其类型就是Func<CallSite object object>)
动态调用站点对象(本例中为<>p__Site )有一个Target属性 它负责引用这一生成好的委托
委托生成之后 动态表达式的执行就体现为委托的执行 其实参由编译器直接 写死 在IL代码中
简化的代码示意如下(通过Reflector得到 为便于阅读 修改了变量名)
object d = ;object CS$ $= d;if (<>p__Site== null)<>p__Site= CallSite<Func<CallSiteobjectobject>> Create(……);d = <>p__Site Target(<>p__SiteCS$ $ );
上述类型推断 方法绑定及IL代码生成的工作都是在程序运行时完成的
( )动态代码很慢吗?
动态编程语言易学易用 代码紧凑 开发灵活 但性能则一直是它的 软肋 为了提升性能 DLR设计了一个三级缓存策略
动态站点绑定对象会为动态调用表达式转换而成的语法树加上相应的测试条件(称为 test ) 构成一个 规则(Rule) 这个规则可以用于判断某个语法树是否可用于特定的动态调用表达式
举个例子 请看以下这个动态表达式
d + d
如果在程序运行时d 和d 都是int类型的整数 则DLR生成的规则为
if( dis int && dis int) //测试条件return (int)d +(int)d ; //语法树
DLR通过检查规则中的 测试条件 就可以知道某个动态表达式是否可以使用此规则所包容的语法树
规则 是DLR缓存的主要对象
前面介绍过的动态站点对象Target属性所引用的委托是第一级缓存 它实现的处理逻辑是这样的
//当前处理规则 属于第 级缓存if( dis int && dis int) //测试条件return (int)d +(int)d ; //满足测试条件 直接返回一个表达式树//未命中 则在第 级 第 级缓存中查找 如果找到了 用找到的结果更新第 级缓存return site Update(site d d );
如果 级缓存中都没有命中的规则 则此动态站点所关联的调用站点绑定对象会尝试创建一个新的规则 如果创建新规则失败 则由当前编程语言(比如)所提供的默认调用站点绑定对象决定如何处理 通常的作法是抛出一个异常
当前版本的DLR第 级缓存了 条规则 第 级则缓存了 条规则
由于DLR自身设计了一个 规则 缓存系统 又充分利用了CLR所提供的JIT缓存(因为所有动态调用代码最终都会转换为CLR可以执行的IL指令 而CLR可以缓存这些代码) 使得动态代码仅仅在第一次执行时性能较差 后续的连续调用其性能可以逼近静态代码
C# 与动态语言的集成
由于几乎所有的编程语言都可以使用抽象语法树来表达 因此 在理论上DLR支持无限多种编程语言间的互 *** 作 在当前版本中 可以实现C#/Visual Basic与IronPython和IronRuby的互 *** 作 相信很快会出现其他动态编程语言的DLR实现
一个有趣的地方是当前基于DLR实现的动态编程语言都以 Iron 开头 比如IronRuby和IronPython IronPython的设计者 DLR的架构设计师Jim Hugunin曾经在微软PDC 大会上解释说主要是为了避免起一个 Python 或 Python for NET 之类 微软味十足 的名字 才有了 IronPython 他强调 Iron 系列动态语言将严格遵循动态语言自身的标准和规范 尊重这些动态语言已有的历史和积累 不会引入一些仅限于 NET平台的新语言特性 并且这些语言的 NET实现保持开源 与此同时 Jim Hugunin指出 Iron 系列语言能很好地与 NET现有类库 编程语言和工具集成 并且能 嵌入 到 NET宿主程序中
( )动态对象通讯协议
由于各种动态编程语言之间的特性相差极大 实现各语言间的互 *** 作是个难题 为此DLR采取了一个聪明的策略 它不去尝试设计一个 通用的类型系统 (CLR就是这么干的) 而是设计了一个 通用的对象通讯协议 规定所有需要互 *** 作的动态对象必须实现IDynamicMetaObjectProvider接口 此接口定义了一个GetMetaObject()方法 接收一个语法树对象作为参数 向外界返回一个 动态元数据(DynamicMetaObject) 对象
DynamicMetaObject GetMetaObject(Expression parameter);
DynamicMetaObject对象向外界提供了两个重要属性 Restrictions引用一组测试条件 Expression属性则引用一个语法树 这两个属性组合起来就是可供动态站点对象缓存的 规则(Rule)
DLR中的 动态站点绑定对象(CallSiteBinder) 获取了DynamicMetaObject对象之后 它调用此对象所提供的各个方法创建 规则 让 动态站点对象(CallSite<T>) 的Target属性引用它 完成动态绑定的工作
( )动态语言集成环境
为了方便地实现静态编程语言与各种动态编程语言间的相互集成 DLR提供了一整套称为 通用寄宿(Common Hosting) 的组件 其中包容ScriptRuntime ScriptScope等类型
下面我们以IronPython为例 介绍如何在 开发的程序中集成动态编程语言代码
首先需要创建一个ScriptRuntime对象 它是一个最顶层的对象 用于在一个应用程序域中 嵌入 一个特定动态语言的运行环境
ScriptRuntime pythonRuntime = Python CreateRuntime();
接着需要创建一个ScriptEngine对象 它是动态语言代码的执行引擎
ScriptEngine engine = pythonRuntime GetEngine( py );
ScriptScope对象类似于中的命名空间 其中可以通过定义一些变量向动态代码传入数据 比如下述代码将一个C# 创建的ExpandoObject对象传给Python代码
ScriptScope scope = pythonRuntime CreateScope();//C#创建动态对象 dynamic expando = new ExpandoObject();expando Name = JinXuLiang ; //动态添加一个字段 //让IronPython接收C#创建的Expando对象scope SetVariable( ExpandoObjectexpando);string pythonCode = print ExpandoObject Name ; //IronPython引擎执行Python语句engine CreateScriptSourceFromString(pythonCode) Execute(scope);
上述示例代码是直接执行Python代码 在实际开发中 更常见的是直接执行Python文件中的代码 假设有一个Calculator py文件 其中定义了一个Add函数
def Add(a b):return a+b
则以下C#代码可以直接执行之
ScriptRuntime pythonRuntime = Python CreateRuntime();dynamic pythonFile = pythonRuntime UseFile( Calculator py );Console WriteLine(pythonFile Add( ));
上述示例说明在DLR的支持之下 可以让静态编程语言使用动态语言所开发的库 反过来 基于DLR实现的动态编程语言也能使用为静态语言所设计的库 比如标准的基类库
这意味着两点
( )我们现在可以将 静态 和 动态 编程语言组合起来 开发出一些具有高度交互性的应用程序 使用静态编程语言搭建系统框架 使用动态编程语言实现交互性 这是一个很值得注意的应用领域
( )将来会出现一些 静态 动态 编程语言同时适用的库 向实现 无所不在的复用 目标又前进了一步
Visual Studio 为新的 NET编程语言F#提供了专门的项目模板 但没有为IronPython和IronRuby之类动态语言的开发提供支持 相信随着动态语言在 NET平台之上的应用日趋广泛 后继版本的Visual Studio会直接支持动态语言的开发
从C# ~ 所走过的路 可以很清晰地看到它的发展轨迹 得到这样的一个结论
未来的编程语言应该是多范式的 具有高度的可组合性 在一个项目或产品中组合多个编程语言 使用多种编程范式会变得越来越普遍
lishixinzhi/Article/program/ASP/201311/21813
右键单击溢出的动态文本行,打开其属性,从中复制文本,然后将其粘贴到适合您所需布局的新文本框中。或者,您可以从头开始,并以所需的方式创建数据驱动的文本。各种动态文本元素(页码,文档标题等)都只是标记,可以插入布局中的任何文本中。在线ArcGIS帮助中有完整的列表。
以上就是关于Swift和SwiftUI全部的内容,包括:Swift和SwiftUI、dva 利用dynamic动态加载modal和component、ibatis映射文件中的<dynamic>节点是作什么用的呀等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)