(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表示一个函

   
   

前言

 动态类型语言,少了静态类型语言必须声明变量类型的累赘,但也缺失了编译时类型检查和编译时优化的好处。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

如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!

分类: Clojure/ClojureScript数签名

总结

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

如果您觉得本文的内容有趣就扫一下吧!捐赠互勉!

 
本文转自 ^_^肥仔John博客园博客,原文链接: http://www.cnblogs.com/fsjohnhuang/p/7203927.html,如需转载请自行联系原作者
 
相关文章
|
Linux iOS开发 Docker
docker报错:New main PID does not belong to service
docker报错:New main PID does not belong to service
446 0
|
4月前
|
存储 消息中间件 Kubernetes
在K8S中,deploy和Statefulset有何区别?
在K8S中,deploy和Statefulset有何区别?
|
7月前
|
应用服务中间件 nginx 容器
error: a container name must be specified for pod pod-base, choose one of: [nginx busybox]
error: a container name must be specified for pod pod-base, choose one of: [nginx busybox]
84 0
|
7月前
|
Shell Perl 容器
kubectl exec -it etcd-master -n kube-system /bin/bashkubectl exec [POD] [COMMAND]
kubectl exec -it etcd-master -n kube-system /bin/bashkubectl exec [POD] [COMMAND]
43 0
|
Docker 容器
docker run 报错“Container XXX is restarting, wait until the container is running“
docker run 报错“Container XXX is restarting, wait until the container is running“
552 0
|
Java
解决:Config service failed to start in 120 seconds! Please check ./service/apollo-service.log...
解决:Config service failed to start in 120 seconds! Please check ./service/apollo-service.log...
157 0
|
Kubernetes 负载均衡 数据中心
K8s学习笔记(3)——Namespace,Pod,Label,Deployment,Service
K8s学习笔记(3)——Namespace,Pod,Label,Deployment,Service
182 1
|
JSON Kubernetes 监控
K8S之yaml 文件详解(pod、deployment、service)
K8S之yaml 文件详解(pod、deployment、service)
9257 3
K8S之yaml 文件详解(pod、deployment、service)
|
Kubernetes Linux Shell
minikube安装kubernetes以及start启动报错解决办法:Unable to find image ‘gcr.io/k8s-minikube/kicbase
使用minikubu安装kuburnetes集群,所遇到的问题,以及如何设置。
2802 1
|
Serverless Perl
R|apply,tapply
R|apply,tapply