• (cljs/run-at (JSVM. :all) "Metadata就这样哦")


    前言

     动态类型语言,少了静态类型语言必须声明变量类型的累赘,但也缺失了编译时类型检查和编译时优化的好处。cljs虽然作为动态类型语言,但其提供Metadata让我们在必要的时候可选择地补充类型提示,以便提高代码可读性和供编译器优化使用。除了上述以外,Metadata还让我们在不影响对象本质的前提下,附加额外信息增强元编程能力。

    Metadata附加的目标

     首先要明确一点的是,Metadata不是任何对象/值都拥有的。只有如下的对象才可附加Metadata

    1. Symbol
    2. Var
    3. Collections(List,Map,Vector,Set)
    4. Record
    5. Type

    meta读取Metadata

     通过meta我们可以获取对象的Metadata,若没有则返回nil
    示例1:获取Var的Metadata

    (def a 1)
    
    (meta #'a)
    ;;=> {:ns cljs.user, :name a, :file "<cljs repl>", :end-column 7, :source "a", :column 1, :line 1, :end-line 1, :arglists (), :doc nil, :test nil}
    

     上述示例1中是(meta #'a)而不是(meta a),前者是获取Var的Metadata,而后者是获取值1的Metadata,显然后者是没有Metadata的。
    示例2:获取Symbol的Metadata

    (def a (with-meta 'a {:something "test"}))
    (meta a)
    ;;=> {:something "test"}
    

     通过with-meta我们可以获取附加了metadata的symbol'a(注意作为入参的symbol'a不会受到影响)。

    with-meta后期追加Metadata

     上面我们已经看到with-meta的使用示例了,下面我们再看看具体的函数签名吧。

    ;; Returns an object of the same type and value as obj, with map m as its metadata.
    (with-meta obj m)
    

     值得注意的是,with-meta会的返回值才会附加上metadata,而入参obj不会附加上metadata。因此需要用绑定来保存结果,以便后续使用。

    (def a
      (with-meta obj m))
    

    定义时附加Metadata

     除了with-meta后期追加外,很多时候我们是在定义时就已经可以明确metadata的了,那么可以两种形式定义metadata。

    完整写法

    ;; 定义Var的metadata
    (def ^{:dynamic true, :tag "test"} a 1)
    
    ;; 读取metadata
    (meta #'a)
    
    ;; 定义Map的metadata
    (def b ^{:something "test"} {:name 1})
    
    ;; 读取metadata
    (meta b)
    

    缩写——Metadata Reader

     有时我们只想定义一两个metadata,完整写法显然有些累赘,那么我们就可以采用metadata reader的写法,小清新一下。

    (def ^:dynamic ^"test" a 1)
    ;;等价于(def ^{:dynamic true, :tag "test"} a 1)
    

     缩写是有限制,所以只能表达如下metadata

    ^:foo ;;=> ^{:foo true}
    ^"foo";;=> ^{:tag "foo"}
    ^foo  ;;=> ^{:tag <value of foo>}
    

    &esmp;至于其它metadata则还是要使用完整写法处理。

    内置的metadata

    :dynamic ;; Boolean, 指定Var为动态绑定
    :private ;; Boolean, 指定该Symbol的访问控制为私有,默认为public
    :doc     ;; String, 设置document string
    :test    ;; Function,不带入参的函数,单元测试函数
    :tag     ;; Class,指定Symbol所指向的Var的数据类型
    

    另外编译器会自动附加一下信息到Var上。

    :file     ;; String
    :line     ;; Int
    :name     ;; Symbol
    :ns       ;; Symbol
    :macro    ;; Boolean,true表示是macro
    :arglists ;; List<Vector>,每个Vector表示一个函数签名
    

    总结

     今天就写到这里,下次继续_
    尊重原创,转载请注明来自:http://www.cnblogs.com/fsjohnhuang/p/7203927.html _肥仔John

  • 相关阅读:
    生成15位或者4位随机数 (主要用于微信支付订单号)
    支付签名 MD5Util 排序工具类
    JVM垃圾回收(GC)
    JVM内存区域
    Java实现经典七大经典排序算法
    Java设计模式之装饰者模式
    Java设计模式之单例模式
    提前批笔试一道算法题的Java实现
    Java设计模式之工厂模式
    文件上传和下载
  • 原文地址:https://www.cnblogs.com/fsjohnhuang/p/7203927.html
Copyright © 2020-2023  润新知