ShoneSharp语言(S#)的设计和使用介绍系列(11)—“类”披炫服靓妆化成“表”
ShoneSharp语言(S#)的设计和使用介绍
系列(11)—“类”披炫服靓妆化成“表”
作者:Shone
声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp。
摘要: 匿名类指类定义体(即代码块)本身,使得类也成为所谓的“一等公民”,类也可以像变量一样进行赋值定义、传递和使用。S#语言的数据类就是程序代码,数据表是该代码运行时对应的数据值,为此本文介绍了数据表、类定义和类实例化的各种使用方法,让你体验S#强大的数据和信息表达能力。
软件: S#语言编辑解析运行器13.6.31,运行环境.NET 4.0,绿色软件,单个EXE直接运行,无副作用。网盘下载链接为https://pan.baidu.com/s/1nv1hmJn
有了前述S#公式、函数以及语句的铺垫,终于进入到本系列的高潮部分介绍———S#类,为配合本文例子,请使用最新软件13.6.31版运行本文示例。
一、引言
世界很复杂,世界也很简单。站在不同角度,收获视图也不一样。前面第四章第二节已经清晰地展示S#符号解析运行视图,提到了:
S#语言开始处理的是数据,最终获得的也是数据,从而形成周而复始的闭环,最终用于实现“数据 → 信息 → 智慧”的完美进化。
S#语言的表达其实也是数据加工成信息的过程,即从没有意义的数据,变成有指定意义的数据(信息)。那么怎么表达呢?
S#第一定律:万物皆对象,对象皆引用。
S#把所有数据值都看成是一个.NET Object对象,可以表达任意数据类型的数据值,而且所有数据都是.NET引用,默认情况下后面的操作不应修改引用数据的内容,而会产生新的应用,保证数据表达或加工过程不产生副作用。
S#第二定律:程序就是树,代码即节点。
S#把程序代码本身也看成是一棵语法数据树,每个树节点对应不同的语法结构代码,可以包含运行过程生成的数据值。因此可以把树节点看成是其数据值的包装,而且树节点本身也是一种数据值,这样就会统一了程序与数据之间的关系,达到“程序即数据,数据即程序”的无缝融合。
S#第三定律:程序以类聚,数据以表分。
第二定律指出程序也是数据,而程序与数据的关系是动态映射的。在程序运行过程中程序的一个数据节点通常保持不变,但其包含的数据值却是根据上下文动态变化的,即不同实例的数据值。因此相同功能的程序代码通常写成一个数据类(简称类),对一个类进行实例化后得到的是一个数据表(简称表)。再次强调与其他语言不同,S#类是程序代码,S#表是该代码运行时对应的数据值,这就是所谓的“类”披炫服靓妆化成“表”。
S#第四定律:无名成列表,有名数据表。
用道德经的名言“无名天地之始,有名万物之母”来描述S#对数据的理解再贴合不过了。上帝创世时的世间万物还都是无名,但取名这事,还是归功于人类的聪明才智,为此人类创造了语言。同样S#语言表达一系列无名的数据集合时采用列表,而表达一系列有名的数据集合时采用的是数据表。可见命名是S#语言表达数据的关键方式,也是把数据加工成信息的必经之路。
上面就是S#语言的圣经,如果您对编程语言领域(PL,Programming Language,网上引起很多争议的王垠就是这方面的专家)有比较深入的研究,本人上述的宏观论断或许会引发您的深思或顿悟。不过不懂没关系,懵懂也很好,下面我就会逐步讲解。
二、数据表
一个无名的数据值是这样子(数值):
10
一系列无名的同类数据值是这样子(数组):
[10, 20, 30]
一系列无名的各类数据值是这样子(列表):
{'box', 10, 20, 30, true}
一系列有名的各类数据值是这样子(数据表):
(1)标准写法
{Name='box', L=, W=, H=, Visible=true}
这种表达让我们看到了盒子及其长宽高等更多的数据含义,促使原始无意义的数据加工成了有意义的信息。这就是数据表的标准写法,可用于表达包含一系列键值数据对的集合,注意与其他语言不同,数据表带有局部变量堆栈,其键就是堆栈中的变量名称,而值就是变量的数据值。
如果每个键值都是数组,那么是不是与数据库的列对应,数据表也就相当于一张数据库中的表。关系数据库的理论已经证明表的关系演算与Lambada演算的表达能力是等价的,可见数据表有多么重要了。
{
Name=['box1', 'box2', 'box3'] ,
L=[, , ] ,
W=[, ] ,
H=[, , ] ,
Visible=[true, false, true]
}
正因为数据表是如此地重要,S#语言支持很多种数据表的扩展写法:
(2)JSON写法
熟悉Javascript的同学有福了,把数据表标准写法的键名写成字符串,中间符号换成冒号,就成为JSON写法。例如:
{"Name":'box', "L":, "W":, "H":, "Visible":true}
现在JSON数据在网络上大行其道,而S#语言可以说就是JSON的超集,可以直接读取JSON,处理JSON数据简直太简单、方便和残暴了。
(3)脚本写法
熟悉脚本文件的同学有福了,把数据表标准写法去掉逗号,花括号换成括号即可简化成脚本写法。例如:
(Name='box' L= W= H= Visible=true)
这种写法没有,分隔符,由于S#把换行也看成空白,因此可以很容易直接导入外部常见的各种脚本或配置文本文件,就是加上()直接解析运行即可。这种脚本数据应用也很广泛,S#语言处理起来也非常简单、方便和残暴。
(4)YAML写法
熟悉YAML和Python的同学有福了,把数据表标准写法去掉逗号和花括号,中间符号换成冒号,加上===可扩展成YAML写法,例如:
===
Name: 'box'
Size:
L:
W:
H:
Visible: true
===
//等价于标准写法
{
Name = 'box' ,
Size = { L = , W = , H = } ,
Visible = True
}
这种写法没有,分隔符,换行缩进自动处理成不同层级的嵌套,可以省略掉好多逗号和花括号,因此表达层级数据非常整齐和简洁,这点与Python处理数据有点异曲同工之妙。S#语言处理YAML也比较简单、方便。
除此之外数据表还有很多从类实例化的写法,本文后面也会专门介绍。简单的数据表也可以看作数据库中表的一条记录,如果有很多条类似这样的记录如下:
{Name='box1', L=10, W=20, H=30, Visible=true}
{Name='box2', L=11, W=21, H=31, Visible=false}
那么说明他们都是同一类型的数据,也就是有共同的模板。这时我们可以使用数据类对他们所属的分类或模板进行抽象表达——数据类(简称类),而实际的数据记录则可以按照该类进行实例化修改成对应的数据表。无名的数据类就是匿名类,有名的数据类通常通过赋值定义或显示定义。
三、匿名类
匿名类(也叫表模板、元表或自定义数据类)指数据类定义体(即代码块)本身,可以当作变量进行传递和使用,使得类成为所谓的“一等公民”。实现方式上也是通过指向类入口的指针、地址或引用传递,在程序后面调用匿名类时则把当前程序跳转到匿名类体上执行,当然每次执行还要处理同名称变量数据值的传递和堆栈进出。
(1)匿名类公式
class 缺省数据表
数据表前加class关键字就可以定义一个匿名类,可用于变量赋值。例如:
class {Name='box', L=, W=, H=, Visible=true}
(2)继承匿名类公式
class : 基类名称 缺省数据表
如果类是从指定的基类派生而来,那么class关键字后面指定一个基类名称即可,实例化的时候是先实例化基类数据再实例化当前类的数据。例如:
class : A {Name='box', L=, W=, H=, Visible=true}
S#类通常是有名字的,上述匿名类的表达方式比较简单便捷,通常用于公式中使用,复杂的请使用下面的类定义。
四、类定义
由于类是一等公民了,因此类通常也可以像变量一样进行赋值定义。
S#有两种类定义形式,但是其类实例化方法是一样的。
(1)隐式类定义
变量名称=匿名类
这种写法最为灵活多变,可使用在任何公式或语句中。因为匿名类被看作普通数据,可以通过命名变量进行传递和使用,无论是传给其他函数作为实参调用,或是作为其他函数的返回值,都没有任何违和感觉。例如:
{
f = class {a=, b=} ,
g = f{a=} , //直接调用,g结果{a=15,b=20}
h = { a = f , b = a{b=} } //变量传递后间接调用,b结果{a=10 b=30}
}
隐式类定义可以使用在任何变量赋值公式中,而且类变量的作用域还可以用专门语法进行修改。
(2)显式类定义语句(注:只能使用在语句中)
class 类名称 缺省数据表;
class关键字显示定义一个类名,进行类变量赋值。例如:
class Test {Name='box', L=, W=, H=, Visible=true}
class 类名称 语句块
与上面类似,只不过类定义体是语句块,支持更复杂代码逻辑,这时和C#的类定义代码很像。例如:
class Test
{
var L=;
var W=;
func GetArea()
{
Return L*W;
}
}
class 类名称 : 基类名称 缺省数据表;
class关键字显示定义一个类名,进行派生类变量赋值。例如:
class Test : A {Name='box', L=, W=, H=, Visible=true}
class 类名称 : 基类名称 语句块
同样类定义体也改成语句块,可支持更复杂代码逻辑,这时和C#的派生类定义代码很像。例如:
class Test : A
{
var L=;
var W=;
func GetArea()
{
Return L*W;
}
}
五、类实例化
一个类其实就是一段代码,只要进行实例化才能转化成为数据表进行使用,这与函数必须进行调用后才能转化为数据值进行使用相类似。
假设前面上下文已定义了类型A如下:
class A { L=10, W=20, Area=L*W }
那么可以使用以下四种S#的类实例化方式,可以用于任何公式和语句中。
(1)无参数的类实例化公式
类名称 {}
直接获得类代码的运行结果即数据表,注意类实例化后时还会把类名添加到数据表中。例如:
{
Rect = class {L = , W = , Area = L * W} ,
b = Rect{} // b结果为 { Class = 'Rect', L = 10 , W = 20 , Area = 200 }
}
(2)带参数的类实例化公式
类名称 { 参数赋值系列 }
传入参数数据值并赋值给类代码中的同名变量,再运行类代码获得的结果数据表。注意如果传入参数没有找到同名变量,那么也会添加到结果数据表中,注意类实例化后时还会把类名添加到数据表中。例如:
{
Rect = class {L = , W = , Area = L * W} ,
b = Rect{L=, X=} // b结果为 { Class = 'Rect', L = 4 , W = 20 , Area = 80, X=50 }
}
(3)带子节点的类实例化公式
类名称 { 类实例化公式系列 }
运行类代码并把子节点作为Children变量附加到的结果数据表,注意类实例化后时还会把类名添加到数据表中。例如:
{
Shape = class {Name = ""} , //定义基类
Line = class : Shape {L = } , //定义线类
Rect = class : Shape {L = , W = , Area = L * W} , //定义矩形类
b = Shape //实例化Shape类(带子节点)
{
Line{ Name = "l", L = }
Rect{ Name = "r", L = }
}
}
//b的计算结果为:
{
Class = 'Shape',
Name = '' ,
Children = {
{ Class = 'Line', Name = 'l' , L = } ,
{
Class = 'Rect',
Name = 'r' ,
L = ,
W = ,
Area =
}
}
}
(4)带参数及子节点的类实例化公式
类名称 { 参数赋值系列 } { 类实例化公式系列 }
传入参数数据值给类代码中的同名变量,再运行类代码并把子节点作为Children变量附加到的结果数据表。注意如果传入参数没有找到同名变量,那么也会添加到结果数据表中,另外类实例化后时还会把类名添加到数据表中。例如:
{
Shape = class {Name = ""} , //定义基类
Line = class : Shape {L = } , //定义线类
Rect = class : Shape {L = , W = , Area = L * W} , //定义矩形类
b = Shape{ Name="l" Extend="扩展数据"} //实例化Shape类(带参数和子节点)
{
Line{ Name = "l", L = }
Rect{ Name = "r", L = }
}
}
//b的计算结果为:
{
Class = 'Shape' ,
Name = 'l' ,
Extend = '扩展数据' ,
Children = {
{
Class = 'Line' ,
Name = 'l' ,
L =
} ,
{
Class = 'Rect' ,
Name = 'r' ,
L = ,
W = ,
Area =
}
}
}
六、XML类实例化
S#还支持类似于XML的类实例化方式,与标准方式一一对应且功能等价,也可以用于任何公式和语句中。
(1)无参数的XML类实例化公式
<类名称/>
与XML相同,例如:
<Rect/>
(2)带参数的XML类实例化公式
<类名称 参数赋值系列/>
与XML相同,赋值序列中间用空白而不是逗号分隔,例如:
<Rect L=4 X=50/>
(3)带子节点的XML类实例化公式
与XML相似,但子节点的写法不同,这样便于扩展,例如:
<类名称/> { 类实例化公式系列 }
<Shape/>
{
<Line Name = "l" L = 5 />
<Rect Name = "r" L = 5 />
}
(4)带参数及子节点的XML类实例化公式
<类名称 参数赋值系列 /> { 类实例化公式系列 }
与XML相似,但子节点的写法不同,这样便于扩展,例如:
<Shape Name="l" Extend="扩展数据"/>
{
<Line Name = "l" L = 5 />
<Rect Name = "r" L = 5 />
}
七、类定义及实例化综合示例
下面给出一个有继承关系的类的语句级别,其实与C#类似,只不过S#更加关注于数据表达层面,不用进行序列化和反序列就能把数据全部计算并表达出来,用于动态扩展各类数据和信息是非常方便的。
{
class Drawing {
var Layer = '';
var Color = 'ByLayer';
var LineType = 'ByLayer';
var LineWidth = 'ByLayer';
var X = ;
var Y = ;
}
class Block:Drawing {
var Rotation = ;
var Scale = ;
var Children = [];
}
class Line:Drawing {
var Length = ;
var Angle = ;
}
class Circle:Drawing {
var Radius = ;
}
class Rectangle:Drawing {
var Width = ;
var Height = ;
}
return Drawing { Name = "图形", Author = "hjx" }
{
Line { Length = }
Circle { Radius = }
Block { Rotation = }
{
Line { Angle = }
Circle { Radius = }
}
};
}
计算结果如下:
{
Class = 'Drawing' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Name = '图形' ,
Author = 'hjx' ,
Children = {
{
Class = 'Line' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Length = ,
Angle =
} ,
{
Class = 'Circle' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Radius =
} ,
{
Class = 'Block' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Rotation = ,
Scale = ,
Children = {
{
Class = 'Line' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Length = ,
Angle =
} ,
{
Class = 'Circle' ,
Layer = '' ,
Color = 'ByLayer' ,
LineType = 'ByLayer' ,
LineWidth = 'ByLayer' ,
X = ,
Y = ,
Radius =
}
}
}
}
}
八、S#语言小结
至今为止,本系列博文把S#的基本语言特性大都介绍过了,还有一些高级特性后续博文继续讲解。不知您对S#语言有何看法?如有请把您理解的优势利弊发表在下面评论中。
总而言之,S#语言是一种基于.NET平台的面向表达的动态语言,他尽量兼收并蓄了其他语言常用的语法特性,把数据值、数组、列表、数据表、函数以及数据类全部都看做是一等公民,并通过对公式和语句两种语法基础结构的对全面支持和扩展,使得该语言化繁为简,表达能力相当出色。
声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp。
软件: S#语言编辑解析运行器13.6.31,运行环境.NET 4.0,绿色软件,单个EXE直接运行,无副作用。网盘下载链接为https://pan.baidu.com/s/1nv1hmJn
ShoneSharp语言(S#)的设计和使用介绍系列(11)—“类”披炫服靓妆化成“表”的更多相关文章
- ShoneSharp语言(S#)的设计和使用介绍系列(7)— 布尔Bool及对象Object
ShoneSharp语言(S#)的设计和使用介绍 系列(7)— 布尔Bool及对象Object 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ ...
- ShoneSharp语言(S#)的设计和使用介绍系列(1)— 开篇
ShoneSharp语言(S#)的设计和使用介绍 系列(1)- 开篇 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. 一 ...
- ShoneSharp语言(S#)的设计和使用介绍系列(4)— 入门概述
ShoneSharp语言(S#)的设计和使用介绍 系列(4)- 入门概述 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
- ShoneSharp语言(S#)的设计和使用介绍系列(3)— 修炼工具
ShoneSharp语言(S#)的设计和使用介绍 系列(3)- 修炼工具 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
- ShoneSharp语言(S#)的设计和使用介绍系列(2)— 掀开盖头
ShoneSharp语言(S#)的设计和使用介绍 系列(2)- 掀开盖头 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSharp. ...
- ShoneSharp语言(S#)的设计和使用介绍系列(10)— 富家子弟“语句“不炫富
ShoneSharp语言(S#)的设计和使用介绍 系列(10)— 富家子弟“语句“不炫富 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/Sho ...
- ShoneSharp语言(S#)的设计和使用介绍系列(9)— 一等公民“函数“爱炫巧
ShoneSharp语言(S#)的设计和使用介绍 系列(9)— 一等公民“函数“爱炫巧 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/Shon ...
- ShoneSharp语言(S#)的设计和使用介绍系列(8)— 最炫“公式”风
ShoneSharp语言(S#)的设计和使用介绍 系列(8)— 最炫“公式”风 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneSha ...
- ShoneSharp语言(S#)的设计和使用介绍系列(6)— 字符串String
ShoneSharp语言(S#)的设计和使用介绍 系列(6)— 字符串String 作者:Shone 声明:原创文章欢迎转载,但请注明出处,https://www.cnblogs.com/ShoneS ...
随机推荐
- redhat7.3 dns服务器配置
1.基本配置 systemctl stop firewalld.service systemctl disable firewalld.service setenforce 0 nmcli conne ...
- Extmail邮件过滤和杀毒
前面整合好了extmail,不过没有测试使用foxmail这种客户端去测试收发邮件功能,今天测试的时候发现了蛮多问题,大部分和/etc/authmysqlrc这个文件的配置和权限相关,都是小问题,折腾 ...
- java中for循环和while循环,哪个更快?--一道面试题
for的 while的
- 数学--数论--HDU 5382 GCD?LCM?(详细推导,不懂打我)
Describtion First we define: (1) lcm(a,b), the least common multiple of two integers a and b, is the ...
- USACO 2.1 海明码 Hamming Codes (模拟+位运算+黑科技__builtin_popcount(n))
题目描述 给出 N,B 和 D,要求找出 N 个由0或1组成的编码(1 <= N <= 64),每个编码有 B 位(1 <= B <= 8),使得两两编码之间至少有 D 个单位 ...
- App 抓包代理设置
1.设置 Fiddler 打开 Fiddler,Tools --> Fiddler Options --> HTPS (配置完后记得要重启 Fiddler) 选中 "D ...
- 入职半年多,Guide哥总结了这些帮助你领先90%程序员的好习惯!
大家好,我是 Guide 哥,这篇文章还是不分享技术文章了,我想简单聊聊一些程序员的好习惯. 其实自己写这篇文章还是很忐忑的,毕竟自己算不上一个优秀的程序员,但也不是那么差.大学学习编程 4 年,工作 ...
- 线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543
学习博客推荐——线段树+扫描线(有关扫描线的理解) 我觉得要注意的几点 1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1] 2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个pu ...
- kafka学习 之 Quickstart
第一步:安装启动kafka 官网链接:https://www.apache.org/dyn/closer.cgi?path=/kafka/2.3.0/kafka_2.11-2.3.0.tgz 进入指定 ...
- Java实现栈(链表和线性表两种方法实现)
一.栈的介绍 任何数据结构都是一种规则 栈就是在最基础的结构--线性结构和链式结构上面定义规则形成的 如果对基本数据结构(线性表和链表)有疑问的同学可以看我之前的博客:https://www.cnbl ...