V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
bmpidev2019
V2EX  ›  分享创造

介绍 Go/ Java /C/C++/ Swift 等编程语言是如何实现范型的

  •  4
     
  •   bmpidev2019 ·
    madawei2699 · 2022-03-27 10:15:53 +08:00 · 7886 次点击
    这是一个创建于 970 天前的主题,其中的信息可能已经有所发展或是发生改变。

    写了篇介绍 Go/Java/C/C++/Swift 等编程语言是如何实现范型的。

    文章地址:编程语言是如何实现范型的 · 构建我的被动收入

    31 条回复    2022-07-22 09:50:40 +08:00
    xLuoBo
        1
    xLuoBo  
       2022-03-27 10:19:30 +08:00 via iPhone   ❤️ 1
    php 才是世界上最好的语言
    sutra
        2
    sutra  
       2022-03-27 10:33:00 +08:00
    「动态与静态的区别在于类型检查发生的阶段,动态是在编译阶段,静态是在运行时。」这句话怎么理解?
    foobear
        3
    foobear  
       2022-03-27 10:41:03 +08:00 via iPhone
    @sutra 反了吧
    zwy100e72
        4
    zwy100e72  
       2022-03-27 11:13:44 +08:00   ❤️ 1
    我认为 Generic Programming 应该翻译为 “泛型”,而不是“范型”。Generic programming 是对具有相同性质的数据做通用的处理,其面向的数据类型是“宽泛”的,因此称为“泛型”是更合适的。
    sutra
        5
    sutra  
       2022-03-27 11:33:16 +08:00
    另外「范型」(而不是「泛型」),这个词是不是写错了?
    bmpidev2019
        6
    bmpidev2019  
    OP
       2022-03-27 11:35:31 +08:00 via iPhone
    @sutra
    @zwy100e72 感谢指证,这个的确写懵逼了,连续整了两天没意识到这个词😂
    bmpidev2019
        7
    bmpidev2019  
    OP
       2022-03-27 11:36:09 +08:00 via iPhone
    @sutra 是的,感谢指正,我应该多检查两遍的
    zwy100e72
        8
    zwy100e72  
       2022-03-27 11:44:06 +08:00   ❤️ 1
    @bmpidev2019 没关系,交流也是提升的一部分,您已经比我做的更好了,因为你写了这样的总结

    看了你的总结,我也对泛型这个玩法有了更清晰的认识,这要感谢您

    如果您希望在公开宣传之前减少瑕疵的话,可以先找身边的同行帮忙审校一下(英语中应该对应是 proof-reading )
    bmpidev2019
        9
    bmpidev2019  
    OP
       2022-03-27 11:55:21 +08:00
    @zwy100e72 有点着急了,因为要赶着出去玩,想着先发出去😄下次得注意点了,谢谢!
    secondwtq
        10
    secondwtq  
       2022-03-28 01:27:40 +08:00
    “透过 Rust 探索系统的本原:泛型” 这个链接错了吧
    bmpidev2019
        11
    bmpidev2019  
    OP
       2022-03-28 07:56:44 +08:00 via iPhone
    @secondwtq 是的,你们看的真仔细😂,感谢!
    shawndev
        12
    shawndev  
       2022-03-28 10:40:41 +08:00
    @secondwtq @bmpidev2019 这里本原也是错别字吧?正本清源的“本源”?
    bmpidev2019
        13
    bmpidev2019  
    OP
       2022-03-28 11:08:51 +08:00 via iPhone
    @shawndev 原文就是这个标题,但是感觉本原好像也有这个意思?
    zdpdpdp
        14
    zdpdpdp  
       2022-03-28 14:51:50 +08:00
    网站挂了
    bmpidev2019
        15
    bmpidev2019  
    OP
       2022-03-28 16:08:57 +08:00 via iPhone
    @zdpdpdp 被墙了
    avv
        16
    avv  
       2022-03-28 16:10:54 +08:00
    @zdpdpdp 刚看过,可以进去!
    iceheart
        17
    iceheart  
       2022-03-28 19:49:55 +08:00 via Android
    C++是弱类型检查语言,哪里弱了?
    lxml
        18
    lxml  
       2022-03-28 20:07:19 +08:00
    @iceheart #17 这里的弱类型指的是两个变量 "1" + 2 能够直接进行相加(语言内部有隐式转换) ,我猜你认为的弱类型应该叫做动态类型。
    bmpidev2019
        19
    bmpidev2019  
    OP
       2022-03-28 20:46:23 +08:00 via iPhone
    @iceheart 主要是指针可以随意转换,失去了类型安全的保障,编译器也无法知道指针里的类型是啥
    danc
        20
    danc  
       2022-03-28 22:30:05 +08:00
    弱类型,感觉不能这么分。比如 Rust ,unsafe 下指针也可以随意转换,按照 C++的说法,是不是也应该放到弱类型
    GeruzoniAnsasu
        21
    GeruzoniAnsasu  
       2022-03-28 22:34:06 +08:00
    @iceheart c++中字符类型和整型是同一种类型:

    '1'+1 => (这里的类型应该是?)
    Leviathann
        22
    Leviathann  
       2022-03-28 22:40:28 +08:00   ❤️ 1
    @danc 现在很少提类型强弱而是提动静,因为强弱本来就没什么意义,影响的东西很小
    bmpidev2019
        23
    bmpidev2019  
    OP
       2022-03-28 22:44:55 +08:00 via iPhone
    @Leviathann 的确,这种分类价值不大,只是一个视角,c/c++放到弱类型主要是指针导致的,还有一些是有隐式类型转换导致类型不强
    misaka19000
        24
    misaka19000  
       2022-03-31 09:48:49 +08:00
    楼主换头像了?
    anonymousar
        25
    anonymousar  
       2022-03-31 10:53:12 +08:00
    强 /弱类型 区分主要是体现在 隐式类型转换 跟指针关系大吗?
    c0xt30a
        26
    c0xt30a  
       2022-04-01 20:58:42 +08:00
    @bmpidev2019 C++ 里用户可以决定是否关掉隐式的类型转换的。这个跟类型的强弱有什么关系?

    最简单的做法是


    void f(int);
    template< typename T > void f(T)=delete;

    也可以用 SFINAE 来约束

    template< typename T>
    std::enable_if_t<std::is_same_v<T, int>> f( T );

    往后一点 C++20 可以用 concept 来约束

    void f(std::same_as<int> auto x);

    未来的 C++23 很可能用 really 来约束

    void f( really int x );
    c0xt30a
        27
    c0xt30a  
       2022-04-02 14:43:30 +08:00
    4.1 过去了,特意说明下,上边回复最后那条是玩笑
    FrankHB
        28
    FrankHB  
       2022-04-08 20:24:40 +08:00   ❤️ 2
    1.先把词输入对。
    范型(paradigm)
    泛型(generics)
    2.讨论泛型,C 放进来是用来嘲讽用的么。
    这还是因为现在 C 有_Generic ,够当作底线了(但是 OP 一点没提)。
    手工复制和旧式 C 宏连当作范型的底线都不配,因为和类型系统完全没有交互。
    (原文评论区说无关是因为预处理器原因,这是错的,因为 pp phase 也是语言规范钦定的一部分,不应作为是否算是泛型实现的准则。否则 multi-stage programming 之类的就尬了。)
    3.不要参考什么强类型弱类型之流只会让概念更加含混的伪劣资料来源。
    所谓的强类型对立的就是“无”类型或者单一类型(unityped)。
    更原则性上的错误在于这根本不属于类型检查,而是确保存在能被检查的类型的前提。
    cf.github.com/FrankHB/pl-docs/blob/master/zh-CN/typing-vs-typechecking.md
    4.装箱本质上和类型系统无关。
    把装箱的外延缩小为几种 manifest typing 的语言的应用实例是一个常见理解偏差。
    (cf.stackoverflow.com/a/69991369
    利用装箱实现泛型只是用了箱和被装的对象的非同一性;技术上,这里拿来装出来的是不是箱并不重要。
    对象布局根本上需要通过 ABI 约定,箱不是描述 ABI 的抽象。
    5.类型擦除和装箱无关。(为什么是 ed 不是 ing ?)
    没有箱的类型擦除一样可以实现某种意义上的泛型。
    6.vtable 不一定是虚“函数”表(就 Java 来说,一般叫虚方法表)。
    虚表这里只是用来替代 RTTI ,跟装箱也无关。
    7.同上,图中的字典传递跟装箱也无关。
    而且跟虚表并列的应该是字典(虽然这个词太滥了),同样是用来实现某种 RTTI 替代品。
    文章和目录里倒是正常了一点。
    原文评论区有说 Type Erasure/Dictionary ,这个也不确切,更准确地,应该是+。两者都算不上是完整的实现技术。
    但是前者是任意 manifest typing 意义上必要的,后者只是针对静态语言静态区分数据和所谓泛型函数的可选优化。
    8.文章里说的 type parameter 暗示实现的说法是错的。
    type parameter 本来就是 parameteric polymorphism 的核心,没 type parameter 的系统根本不会叫做泛型。
    原文的评论区也指出了这一点。
    要有区别,就是 typing 意义上的强度,例如类型系统是否允许支持所谓的 non-type parameter (根本地,形式上还是 type ,比如 dependent type )。
    9.文章链接的《透过 Rust 探索系统的本原:泛型》里把泛型函数从参数化类型中独立出来的做法在概念上是错的。
    泛型函数的区别无非是类型参数和→这个类型构造器的交互,所以是参数化类型的一部分。
    如果类型系统允许一个值同时居留于不带有→和带有→的类型(如类型擦除可以把*→*这个 kind 擦回*),那么单独考虑泛型函数差不多完全就是实现细节。
    当然,考虑到带有→的 STLC (λ→)是 lambda cube 往其它类型系统(典型地,System F(λ2))扩展的原点,基本上会涉及泛型函数的语言都不允许这样做,即便类型擦除有能力实现;所以这点很容易被一般的作者忽视掉。
    bmpidev2019
        29
    bmpidev2019  
    OP
       2022-04-08 22:59:30 +08:00 via iPhone
    @FrankHB 感谢这么详细而专业的反馈!你说的有些我还没能理解,不过我会继续对文章做一定的修改。
    lxdlam
        30
    lxdlam  
       2022-04-09 12:35:47 +08:00   ❤️ 1
    @FrankHB 说得很好,感谢!昨天回复的比较着急,今天来看很多地方说的确实是不够准确的,关于 C 的部分我的本意其实是说纯文本替换并没有 type level 的工作,所以不算泛型,最后没写清楚。
    chingli
        31
    chingli  
       2022-07-22 09:50:40 +08:00
    我最近也正在学泛型,并准备写一篇读书笔记,正好就看到你这篇了。结合你的文章、文章末尾和这里的精彩评论,让我引以为戒了。

    不过我觉得你要介绍泛型,还是不要东拉西扯太多不太相关的东西,另外要多参考一些权威的解释和论文,然后用自己的话复述出来,从目的、方法、效果等方面去写,要让人能快速入坑,逐渐深入。

    比如这些参考文献:

    * 维基百科的 “Generic programming”: https://en.wikipedia.org/wiki/Generic_programming

    * What is Generic Programming?: https://web.archive.org/web/20051225114849/https://lcsd05.cs.tamu.edu/papers/dos_reis_et_al.pdf

    * Generic programming: https://codedocs.org/what-is/generic-programming

    * What is Generic Programming? : http://www.elegantcoding.com/2012/04/what-is-generic-programming.html

    期待楼主再写一篇!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1347 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:49 · PVG 07:49 · LAX 15:49 · JFK 18:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.