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

总结

今天就写到这里,下次继续^^ 尊重原创,转载请注明来自^^肥仔John

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小詹同学

Python系列之——字符串格式化(xiaozhan is a boy of 22 years old.)

不知道小伙伴有没有遇到过字符串输出有格式要求的情况呢?今天小詹学习分享一波python的字符串格式化的方法。学以致用,首先我们得明确为什么要格式化字符串输出,以...

7420
来自专栏余林丰

Java中net.sf.json包关于JSON与对象互转的坑

  在Web开发过程中离不开数据的交互,这就需要规定交互数据的相关格式,以便数据在客户端与服务器之间进行传递。数据的格式通常有2种:1、xml;2、JSON。通...

42550
来自专栏达摩兵的技术空间

前端面试题分享001

解释 :要注意的是函数中的this与运行环境强相关,与定义环境不相关。所以下面的代码段中,当直接通过对象属性方法中去调用时,其都可以访问到对象的属性,但是当其变...

9740
来自专栏老司机的技术博客

人人都能学会的python编程教程4:关系运算符与循环

在python当中,if condition1:(注意最后的冒号:)称为“语句头”。冒号:之后另起一行缩进的是“语句体”,语句体的行数不限,但至少有一行,否则需...

34990
来自专栏恰童鞋骚年

正则表达式30分钟入门教程--deerchao

原文地址:http://www.cnblogs.com/deerchao/archive/2006/08/24/zhengzhe30fengzhongjiaoc...

29640
来自专栏玄魂工作室

如何学python 第十一课 元组与字典

第十一课 元组与字典 欢迎回来。上一期的如何学python里,我们讨论了函数。我们今天将要学习的是两种类似于列表(list)类型的数据类型。我们先介绍’元组’...

32140
来自专栏java达人

js的回调函数详解

在Javascript中,函数是第一类对象,这意味着函数可以像对象一样按照第一类管理被使用。既然函数实际上是对象:它们能被“存储”在变量中,能作为函数参数被传递...

39750
来自专栏Ryan Miao

Java String.split()用法小结

在java.lang包中有String.split()方法,返回是一个数组 我在应用中用到一些,给大家总结一下,仅供大家参考: 1、如果用“.”作为分隔的话,必...

353110
来自专栏iOS122-移动混合开发研究院

【读书笔记】A Swift Tour

素材:A Swift Tour 推荐下载Playground:Download Playground objc 自己较为熟悉,想熟悉下风头正劲的 swift。就...

37180
来自专栏冰霜之地

JavaScript 新手的踩坑日记

在1995年5月,Eich 大神在10天内就写出了第一个脚本语言的版本,JavaScript 的第一个代号是 Mocha,Marc Andreesen 起的这个...

10420

扫码关注云+社区

领取腾讯云代金券