是否有除了d其他语言与静若?
-
19-09-2019 - |
题
我觉得D的static if
是一个有趣的语言功能。提示我的问题:是否有编译语言中,编译器代码的一个强大的概念,也有语言设备访问他们的其他例子
例如,该代码提供类似的东西从Python来repr
:
char[] repr(T)(T value) {
static if (is(typeof(value.__repr__))) { // class T provides a "repr()" method
return value.__repr__();
} else static if (is(T:string)) {
return `"` ~ value ~ `"`;
// ...other cases...
} else {
return toString(value);
}
}
我觉得这是很酷的,因为它允许不同的,更全面的方法来所做的超载,这是怎样的一种内而外的方法,使代码更动态,相比这样的功能。例如,编译器知道我班有多少场了,但有没有办法让我的代码在编译时访问这些信息在大多数语言。
警告:最后一段有意见的,但我刚才的意思是提供一些动力和澄清我的问题,不会引起争议。我只是想看看是否有其他的编译语言具有这样一些特点。
解决方案
与实际宏任何语言具有如果静态的形式。例如Lisp和 Nemerle 让你构建一个宏扩展到使用的编程结构,如“如果”和代码-loops。这些基本上是编译时决定,让你做一些类似,如果静态的东西。在Nemerle宏的情况下基本上是插件到被在编译时执行的编译器。
在C ++有提高MPL 库具有种静若一>可以使用的两种类型之间进行选择。你可以把两种类型里面的一些代码的run()成员,并得到有点儿类似的东西,但很繁琐的语法。
例如与升压MPL你可以做这样的事情:
struct float_impl {
static void run() { /* float case code */ }
}
struct int_impl {
static void run() { /* int case code */ }
}
typedef typename if_<
is_same<T, float>
, float_impl
, int_impl
>::type impl_t;
impl_t::run();
在d那会是:
static if(is(T == float)) {
/* float code */
}
else {
/* int code */
}
其他提示
有关一个“语言的代码意识”,有没有更好的我见过比Lisp和宏观的设施 - 具体而言,Common Lisp的。但贸易有大部分的时间对象的类型没有在编译时或宏扩展时已知的。对于文字的类型是已知的,所以你可以发现,测试,看看是否一个对象是文字咄咄逼人的宏的例子,如果是这样,对待它的一种方式 - 也许基于它的类型 - 否则准备检测变量用于运行时类型检查。
下面是我改编自 CLLIB 库的示例的 CLOCC的(部分的库)几年前。我们的目标是提供将砍前缀字符串一些其他的字符串匹配前缀的功能。前缀可以在宏扩展时已知或者也可能不是。如果是,我们就可以进行优化:计算前缀的长度第一,并嵌入它作为一个常量,因此,它不是在每次调用生成的函数重新计算。宏是艰巨的在第一,但实际产生的代码是小的。
(defmacro after-prefix-core (comparison-op prefix string &optional length)
"Similar to cllib:string-beg-with-cs."
(flet ((chop (prefix prefix-length string string-length)
`(when (and (>= ,string-length ,prefix-length)
(,comparison-op ,prefix ,string :end2 ,prefix-length))
(subseq ,string ,prefix-length ,string-length))))
(let* ((gstring (gensym "STRING-"))
(gstring-length (gensym "STRING-LENGTH-")))
`(let* ((,gstring ,string)
(,gstring-length ,(or length `(length ,gstring))))
,(if (stringp prefix)
;; Constant -- length known at expansion time.
(let ((prefix-length (length prefix)))
(chop prefix prefix-length gstring gstring-length))
;; Other form -- length not known at expansion time.
(let ((gprefix (gensym "PREFIX-"))
(gprefix-length (gensym "PREFIX-LENGTH-")))
`(let* ((,gprefix ,prefix)
(,gprefix-length (length ,gprefix)))
,(chop gprefix gprefix-length gstring gstring-length))))))))
(defmacro after-prefix (prefix string &optional length)
"Similar to cllib:string-beg-with."
`(after-prefix-core string-equal ,prefix ,string ,length))
(defmacro after-prefix-cs (prefix string &optional length)
"Similar to cllib:string-beg-with-cs."
`(after-prefix-core string= ,prefix ,string ,length))
请参阅的形式
(if (stringp prefix)
在中间?这是检查在宏扩展时间的第一个参数,并根据该参数是否是文字或符号,其类型可以是或可以不是已知的。如果类型是一个符号,我们假设,我们应该等待,直到运行时它重新考虑作为一个变量指向某个其它值。
下面是形式(after-prefix foo bar)
膨胀:
(LET* ((#:STRING-5340 BAR) (#:STRING-LENGTH-5341 (LENGTH #:STRING-5340)))
(LET* ((#:PREFIX-5342 FOO) (#:PREFIX-LENGTH-5343 (LENGTH #:PREFIX-5342)))
(WHEN
(AND (>= #:STRING-LENGTH-5341 #:PREFIX-LENGTH-5343)
(STRING-EQUAL #:PREFIX-5342 #:STRING-5340 :END2 #:PREFIX-LENGTH-5343))
(SUBSEQ #:STRING-5340 #:PREFIX-LENGTH-5343 #:STRING-LENGTH-5341))))
注意,变量#:PREFIX-LENGTH-5343
被绑定到的计算长度FOO
的,这里绑定到变量#:PREFIX-5342
。
现在看看扩张形式(after-prefix "foo" bar)
,其中现在的前缀是一个字符串文字:
(LET* ((#:STRING-5463 BAR) (#:STRING-LENGTH-5464 (LENGTH #:STRING-5463)))
(WHEN (AND (>= #:STRING-LENGTH-5464 3) (STRING-EQUAL "foo" #:STRING-5463 :END2 3))
(SUBSEQ #:STRING-5463 3 #:STRING-LENGTH-5464)))
现在没有计算的“foo”的长度;它的内联为3。
这似乎是在这个例子太多的工作,但能够做这样的事情是一个很好的动力有,因为你的问题冠瘿。
static_if
已经提出了C的下一个版本++(C ++ 1Y)。它最初被提出用于C ++ 11但被明显延迟。