Concept消除了大量的特化需求

33 views
Skip to first unread message

longshanksmo

unread,
Sep 15, 2007, 7:26:33 PM9/15/07
to TopLanguage
呵呵,不好意思,我还是喜欢讨论concept。我是个"抽象迷"。:)
从前天开始,concept_map的特化一直在我脑子里转悠,总觉着它有着非常特别的作用。现在想明白了,它不但可以做concept
adapter,而且可以消除很多特化。比如,过去我们需要对指针执行特化时,一般这么写:
template<typename T> class X; //primary模板,必须有,有时就做成没有body的纯声明
template<typename T> class X<T*> {...};
现在,有了concept和concept_map则可以这样:
concept Pointers<typename T> {...};
template<typename T> concept_map Pointers<T*> {};
concept Refences<typename T> {...};
template<typename T> concept_map Refences<T&> {};
这样所有的指针类型和引用类型就同Pointers和Refences绑定了。使用的时候就很方便了,而且含义也很直观(顺着类型参数读就是了,从左往
右):
template<Pointer P> class X{...}; //当类型为指针,用这个模板
template<Refences R> class X{...}; //当类型为引用,用这个模板
既简洁,又直观,简直是美丽。:-D
同样也可以这么处理函数、成员等等。基本上就是把那些traits改成concept_map就行了。
concept六君子真是天才!他们怎么就知道要做成这样?
这下不会有人再抱怨模板(特化)难以理解和繁琐了吧。:)

red...@gmail.com

unread,
Sep 15, 2007, 9:35:53 PM9/15/07
to pon...@googlegroups.com
是很有用.
先回到D 的 template concept 讨论吧, 我觉得 D 的 concept 不是 static if,
而是
/
TemplateTypeParameterSpecialization/:
/TemplateValueParameterSpecialization/:

Template parameter specializations constrain the values or types the
/TemplateParameter/ can accept.


例如:

template TFoo(T) { }
alias TFoo!(int) Foo1; // (1) T is deduced to be int
alias TFoo!(char*) Foo2; // (1) T is deduced to be char*

template TBar(T : T*) { }
alias TBar!(char*) Foo3; // (2) T is deduced to be char

template TAbc(D, U : D[]) { }
alias TAbc!(int, int[]) Bar1; // (2) D is deduced to be int, U is int[]
alias TAbc!(char, int[]) Bar2; // (4) error, D is both char and int

template TDef(D : E*, E) { }
alias TDef!(int*, int) Bar3; // (1) E is int // (3) D is int*

也很清晰易用.

但是, 对于 T 有一个成员叫做 clone 这种用模板A匹配, 有成员叫做 copy 用模
板B匹配这种, 我不知道应该怎么做简单清晰, work-around 肯定是有的, 但是我
一点都不喜欢迂回的方法, 迂回的方法, 不能直接表达思想, 给可读性带来很大麻烦.

C++ 中, 我最不喜欢的, 也是这么迂回的东西太多, 太多东西语言不支持, 而通过
一些什么什么常用范式来解决问题, 还以此标榜为语言强大, 实际上就是编译器抱
残守缺, 不肯进化. ---- 对我来说, 这才是 C++ 的 "思维负担" --- 写代码和读
代码都要弯弯绕才能知道实际目的, std::string 后台做什么那种倒算不了思维负担.


longshanksmo 写道:

longshanksmo

unread,
Sep 16, 2007, 12:04:06 AM9/16/07
to TopLanguage
恰恰相反,concept和concept_map的出现便是为了消除那么多迂回的东西(论据的完整版在六君子的论文里和proposal里,通俗版在
pangba的blog里)。concept最初可能是为了提供模板参数的约束而提出的。但是,concept本身却是一个非常,怎么说呢,非常基础,
非常本质的东西。有很多事物的运作都是依赖于本质的东西,本质的东西则可以"一一当十"地解决问题。所以,设计者们有意无意地创造了一个非常本质的工
具。
concept实际上可以认为是一种对类型的描述。他并非描述类型所有方面的特质,但却描述了最关键,对编程最有帮助的部分--类型的行为(通过成员函
数和相关的自由函数)。而且这种描述的粒度可以达到最细的程度,而不仅仅是指针、引用这种大粒度描述。concept_map则是对concept的控
制和补充。
正因为如此,concept和concept_map一口气提供了众多功能:模板参数约束(static if)、static tag
dispatch(模板特化)、traits(traits模板、特化)、更简单的显式和局部特化形式。更重要的是,它允许所有这些功能都以一种完全统
一的形式。也就是说,可以以直接,不迂回的方式表现这些功能。
C++,包括其他一些语言,如C、Ada、Java等,发展过程中的核心问题,实际上是最初创建的语言力图解决过去语言的某些问题,但随着语言的逐步扩
展(应程序员们的要求),不断加入新特性。于是,被迫采用很多并非最理想的形式实现。为此,产生了许多缺陷和复杂性。C++的初期也非常简单,但由于加
入的特性较其他语言更多,更具革命性,所以其缺陷和复杂性也是"出类拔萃"的。
D有了一个很好的起点,大量的语言特性、缺点、优点,众多语言都已经为它进行了尝试。如果D仅仅试图消除C++的缺点,那么,可以说它并没有真正地从C
++身上吸取教训。他应该有更宏大的目标。从主体功能而言,D并没有超越C++的范畴。仅仅简化语言的使用并不能满足程序员们未来的需求。程序员永远是
贪得无厌的。他们不会记得D有多么好用,他们会认为这是理所当然,天经地义的。他们只会说:为什么没有这个?为什么没有哪个?正是程序员的这种秉性,才
使得C++编程如今这副德行。所以,D应该尽可能地打好基础,尽可能减少未来新特性带来的冲击。好在D目前的基础不错,看上去也没有什么排斥
concept的东西,加入concept只会有好处,不会有坏处的。

pongba

unread,
Sep 16, 2007, 12:56:06 AM9/16/07
to pon...@googlegroups.com
On 9/16/07, longshanksmo <m...@seaskysh.com> wrote:
如果D仅仅试图消除C++的缺点,那么,可以说它并没有真正地从C
++身上吸取教训。

这句话我深以为然。仅仅试图消除C++缺点,那目光还是往后看了。

他应该有更宏大的目标。

其实这个宏大的目标,用BJ的话来说,就是,Aim for generality。提供"一般性"的表达工具。但话说回来,未来到底是属于general-purpose语言的,还是属于各个领域语言多语言分工协作的。到底是general-purpose语言通过把库扩展到各个领域去,再针对领域库编程。还是各个领域语言内建领域能力然后互相跨语言交互。真不好说..

C++的理念里一句话很有理想主义光辉:对一门特定问题领域怎么编程呢?先把库扩展到他们丫家里,然后针对库来编程。正因为这个原因,C++才致力于成为一门有助于设计更好的库的语言。这个目标能不能实现呢?如果真能理想实现的话,通用语言跟领域语言的区别就不是那么大了呢... 

red...@gmail.com

unread,
Sep 16, 2007, 1:34:25 AM9/16/07
to pon...@googlegroups.com

pongba 写道:

> On 9/16/07, longshanksmo <m...@seaskysh.com> wrote:
>
> 如果D仅仅试图消除C++的缺点,那么,可以说它并没有真正地从C
> ++身上吸取教训。
>
>
> 这句话我深以为然。仅仅试图消除C++缺点,那目光还是往后看了。
>
> 他应该有更宏大的目标。
>
>
> 其实这个宏大的目标,用BJ的话来说,就是,Aim for generality。提供"一般
性"的表达工具。但话说回来,未来到底是属于general-purpose语言的,还是属于
各个领域语言多语言分工协作的。到底是general-purpose语言通过把库扩展到各
个领域去,再针对领域库编程。还是各个领域语言内建领域能力然后互相跨语言交
互。真不好说..
>
D 我看的时间还不很长, 从我所看到的地方, D 1.0 基本上已经将C++ 的大部分缺
点解决了, 包括OO 和 GP 中多数的问题 (concepts 这个似乎还没有完成, 不过和
现有的东西不会冲突.)

D 2.0 着重解决的问题更多的是C++ 现有缺陷之外的考虑了. 包括更多的 fp 特
性, 更好地支持并发, AST macro等东西. 其中的 AST macro 具体如何我没有找到
文档, 但是这个东西, 号称是可以用来扩展语言的语法的一个东西.

这样的话, D 完善支持的范式有 过程式, OO, GP; meta programming 支持得不
错, 支持一点 fp; AST macro 可以用来扩展语法或者用来做 DSL, aspect 没有看
到什么动作, 不过 aspect 这个东西, 实用中发挥的作用听说也不是特别的大.

Walter Bright 的一个观念是, 一个特性或者工具, 只有很方便就能够得到的时
候, 才能够得到广泛的使用, 所以他将 unittest, code covergage, profile 都
建到语言内部里面去了, 我对这个倒是非常满意. DSL 的态度, D 社区里面有过讨
论, 我没有完整看完,但是印象是, 他们认为很多应用, 有一个 DSL 会更简单.

这些特征, 对于D的目标, 系统编程, 看起来也差不多了, 在语言技术没有出现大
的突破之前 (例如 GP 的意义被挖掘那种)
, 这个语言应该都还可以比较干净.

不过, 如果他成功的话, 应该也会有一些需求将其推向偏应用层, 那边又会出现什
么新语言要求呢 ?

Tango 2.0 milestone 那里有一个 wishlist 是 derailed, 是 D 语言版本的
rail, 这个东西将会综合考验 D 的效率, 表达力(包括 Dhtml template DSL), 使
用简洁方便等东西了.


> C++的理念里一句话很有理想主义光辉:对一门特定问题领域怎么编程呢?先把
库扩展到他们丫家里,然后针对库来编程。正因为这个原因,C+ +才致力于成为一
门有助于设计更好的库的语言。这个目标能不能实现呢?如果真能理想实现的话,
通用语言跟领域语言的区别就不是那么大了呢...
>

这个我觉得基本很难, 库可以提供功能, 但是很难有好的表达力, 例如, 语言不支
持, 用库做一个 foreach, 看起来就难受.

如果 AST macro 做得真是强, 那可能倒是能够有些作用.

Atry

unread,
Sep 16, 2007, 1:55:09 AM9/16/07
to pon...@googlegroups.com
嗯,我是昨天晚上才开始看 D 的,时间还很短。我打算编译 D 程序的时候不用什么 makefile 了,就写一个 build.d 的程序用来编译。到时候要编译的话,就敲一个 dmd -run build.d 就行了。

在07-9-16,red...@gmail.com <red...@gmail.com> 写道:

Jian Wang

unread,
Sep 16, 2007, 1:56:18 AM9/16/07
to pon...@googlegroups.com
问题是通用语言的库的学习成本并不低。比如说现在的C++的库,从MFC到SmartWin++可以留用的知识非常少。而C#的数据库操作以及web开发这样的专用语言却很容易学习。
 
像QT这样的库很多地方都不够优雅,或者说很土。但是却很容易学习使用。很多时候够用也就可以了。
 
在07-9-16,red...@gmail.com <red...@gmail.com> 写道:

Atry

unread,
Sep 16, 2007, 1:56:59 AM9/16/07
to pon...@googlegroups.com
我写 C++ 程序的时候已经受够了 bjam 奇形怪状的语法了。 make 语法简单可是又太弱。干脆直接用 D 来编译 D 算了。 D 的文件系统库里面应该有检测最后修改时间之类的功能吧?

在07-9-16,Atry <pop....@gmail.com > 写道:

oldrev

unread,
Sep 16, 2007, 2:02:18 AM9/16/07
to pon...@googlegroups.com
现在编译稍具规模的 D 程序一般都是用 D Shared Software System 了:
http://www.dsource.org/projects/dsss

不过我一般使用 Rake

在 2007-09-16日的 13:56 +0800,Atry写道:

oldrev

unread,
Sep 16, 2007, 2:06:16 AM9/16/07
to pon...@googlegroups.com
D 的 template mixin 已经有那么点 AOP 的意思了。


在 2007-09-16日的 13:34 +0800,red...@gmail.com写道:

red...@gmail.com

unread,
Sep 16, 2007, 2:10:41 AM9/16/07
to pon...@googlegroups.com
不必这么麻烦, 用 dsss 简单.

dsss 可以自动分析 d 之间的 import 关系, 你只需要指明 main.d 这个文件, 剩
下都不用管了.

但是 dsss 和 dmd 的object 输出在一些诡异的地方有冲突, 我自己碰到的问题
是, 告诉我的代码中Sprint 这个模板的实例化和 tina 里面对 Sprint 的实例化
冲突了, 天地良心, 模板的实例化不应该冲突的. 我的解决方法是告诉我冲突的时
候, import tina 那个文件进来就好了.

这里面 dsss 作者和 walter 估计还没有想好最后的处理方式, walter 说, 如果
要避免问题, 要修改目前已经很 stable 的输出代码, 要将里面一个优化去掉, 大
概要多花几十个点的编译时间; dsss 作者说, 你做了这个优化, 那么无论
project 有多少个文件, 我都可以一次全部编译, 否则我要一个一个文件编译, 这
是局部和整体的问题. 我不管他们, 就用 import 的方式搞定.

我用 dsss 的方法, 下载解开 dsss
然后
dsss net install dmd
安装 dmd

dsss net install tango
安装 tango

就可以开始工作了.

这样做的话, 无论用 gdc, photos, tango, 之间的一些版本处理的问题, 不用自
己操心.

我的 项目 dsss.conf 配置文件如下, 我的 test.d 是主文件. 我有很多控制
debug 代码和 unittest 代码的选项.
name=test

[*]
buildflags+=-w

#带优化的
#buildflags+=-O -release -inline

#调试
buildflags+=-g

#单元测试和 cov
#buildflags+=-cov


#要开单元测试, 则需要设置debug(module), 另外, 有debug(ut_all),
debug(all), 但是没有 debug(trace_all)
# debug(ut_module) 和 debug(trace_module) 都会启动 debug(module)
buildflags+=-unittest -debug=all

buildflags+=-debug=util_pktcomm -debug=ut_util_pktcomm
-debug=trace_util_pktcomm
#buildflags+=-debug=util_memory -debug=ut_util_memory
-debug=t1race_util_memory
#buildflags+=-debug=util_intrusive -debug=ut_util_intrusive
-debug=trace_util_intrusive

#是否跟踪析构函数 (和模块自身的 trace 一起都enable, 才会显示出来)
#buildflags+=-debug=trace_dtor

[test.d]
target=test

Atry 写道:

Atry

unread,
Sep 16, 2007, 2:11:10 AM9/16/07
to pon...@googlegroups.com
D 语言描述能力这么强,何必用什么 dsss.conf 呢?直接用 D 语言自己做配置文件不行吗?

在07-9-16,oldrev <old...@gmail.com> 写道:

longshanksmo

unread,
Sep 16, 2007, 5:31:48 AM9/16/07
to TopLanguage
我总有一个感觉,程序员似乎都有general-purpose的倾向。C最初为了编写Unix而创造,Ada重点在实时系统上,C++为了消除C的一
些问题。Java为了简化语言的使用。都是针对某一特定目的领域的应用而产生。但在发展的过程中,随着使用者的增加,五花八门的特性,只要能加上,都有
人试图往里塞。于是,语言也就逐渐地变成了general-purpose的了。这也难怪,一方面,人总是有从众心理;另一方面,单一的
general-purpose语言有利于从总体上降低整个编程界的学习使用成本。
C++的强大之处并非仅仅在于OOP、GP什么的。这些东西是死的,很容易模仿。C++的真正特殊之处来源于Bjarne的一个理念:让用于定义类型同
内置类型一样对待。这使得C++的类型体系是可以扩展的。但C++在这方面仅仅走出了第一步,并没有完全达到这个目标。实际上这个目标隐含的一个终极理
想:建立一个基础的语言核心,通过运用语言构建的库,或类似的模块,实现某些特定的语言特性。也就是在语言上创建语言。这就要求语言核心充分地接近最基
本的"道"(我不知该用什么词汇描述这个东西),是一种极端灵活的语言核心。目前C++可以勉强地做到在语言中创建一种简单的、生涩的"子语
言"(《Template meta-programming》中有整整半本在讲述这个问题)。但还不能"控制"子语言的特性。我不是语言专家,不知道
未来是否能够达成这个目的,但这应该是一个房展的方向。
Reply all
Reply to author
Forward
0 new messages