在我用PHP开发的这些年里,我总是听说使用eval()是邪恶的.
考虑以下代码,使用第二个(更优雅)选项是否有意义?如果没有,为什么?
// $type is the result of an SQL statement
// e.g. SHOW COLUMNS FROM a_table LIKE 'a_column';
// hence you can be pretty sure about the consistency
// of your string
$type = "enum('a','b','c')";
// possibility one
$type_1 = preg_replace('#^enum\s*\(\s*\'|\'\s*\)\s*$#', '', $type);
$result = preg_split('#\'\s*,\s*\'#', $type_1);
// possibility two
eval('$result = '.preg_replace('#^enum#','array', $type).';');
Run Code Online (Sandbox Code Playgroud) 在elisp我可以评估或作为一个函数就像+.
(or nil 0 nil) ==> 0
(+ 1 0 1) ==> 2
Run Code Online (Sandbox Code Playgroud)
我可以使用apply来将+应用到列表中
(apply '+ '(1 0 1)) ==> 2
Run Code Online (Sandbox Code Playgroud)
所以,我会想或者会以同样的方式工作,但事实并非如此.
(apply 'or '(nil 0 nil)) ==> error: (invalid-function or)
Run Code Online (Sandbox Code Playgroud)
我想这是来自用于实现短路评估的一些内部魔术.如何使用apply对列表执行或操作?
PS我想要的应用程序是找出命令行上的任何元素是否与特定模式匹配,所以我写的重要部分是:
(apply 'or (mapcar (lambda (x) (string-match-p "pattern" x)) command-line-args))
Run Code Online (Sandbox Code Playgroud)
但它不起作用
在Clojure,
(def x 3)
(eval '(prn x))
Run Code Online (Sandbox Code Playgroud)
打印3,而
(let [y 3]
(eval '(prn y)))
Run Code Online (Sandbox Code Playgroud)
和
(binding [z 3] (eval '(prn z)))
Run Code Online (Sandbox Code Playgroud)
生成'无法解析var'异常.
据http://clojure.org/evaluation,eval,load-string,等生成临时命名空间来评估它们的内容.因此,我希望上述代码示例都不起作用,因为(def x 3)它是在我当前的命名空间中完成的,而不是由当前命名空间创建的eval.
eval使用绑定变量的表单而不使用def?谢谢!
可能重复:
为什么eval邪恶?
我读过人们声称当使用任意用户输入代码运行时,eval是不安全的.我在访问文件系统等服务器上运行的其他语言中理解这一点.但是,为什么在浏览器中执行代码时这很重要?毕竟,你不能只是启动Firebug并写任何你想要的任意脚本吗?那么eval有何不同呢?
在我的脚本中,我希望能够根据特定条件写入文件或stdout.我很好奇为什么这在我的脚本中不起作用:
out=\&1
echo "bird" 1>$out
Run Code Online (Sandbox Code Playgroud)
我尝试了不同的引号组合,但我继续创建一个"&1"文件,而不是写入stdout.我该怎么做才能让我的工作方式如何?
在我完全理解如此强大的lisp宏的过程中,我想到了一个问题.我知道关于宏的一条黄金法则是"当一个函数完成工作时不要使用宏".然而阅读第9章 - 实践:构建单元测试框架 - 从实用Common Lisp I一书中介绍了下面的宏,其目的是消除测试用例表达式的重复,伴随着结果错误标记的风险.
;; Function defintion.
(defun report-result (result form)
(format t "~:[FAIL~;pass~] ... ~a~%" result form))
;; Macro Definition
(defmacro check (form)
`(report-result ,form ',form))
Run Code Online (Sandbox Code Playgroud)
好的,我理解它的目的,但我可以使用函数而不是宏来完成它,例如:
(setf unevaluated.form '(= 2 (+ 2 3)))
(defun my-func (unevaluated.form)
(report-result (eval unevaluated.form) unevaluated.form))
Run Code Online (Sandbox Code Playgroud)
我正在尝试编写一个将生成n个函数的宏.这是我到目前为止所拥有的:
; only defined this because if I inline this into make-placeholders
; it's unable to expand i# in ~(symbol (str "_" i#))
(defmacro defn-from [str mdata args & body]
`(defn ~(symbol str) ~mdata ~args ~@body))
; use list comprehension to generate n functions
(defmacro make-placeholders [n]
`(for [i# (range 0 ~n)] (defn-from (str "_" i#) {:placeholder true} [& args] (nth args i#))))
; expand functions _0 ... _9
(make-placeholders 9)
Run Code Online (Sandbox Code Playgroud)
我得到的错误是:
java.lang.ClassCastException: clojure.lang.Cons cannot be cast to java.lang.String
Run Code Online (Sandbox Code Playgroud)
而且我不确定这意味着什么,但我有这个模糊的概念(因为...)没有像我认为的那样在宏内部工作.
作为输入验证的一种形式,我需要强制一个字符串'9>6'来评估一个布尔值.
除了评估字符串,我似乎无法找到解决方法.
我一直都听说过eval的邪恶(特别是因为我正在验证表单输入),关于它可以评估任何脚本和性能问题的事实.
但....
在我的案例中是否有任何替代方案(处理关系运算符)?
var arr = ['<9', '>2'];
var check = function (a) {
return arr.every(function (x) {
var string = '';
string += a + x;
try {
return eval(string);
} catch (e) {
return false;
}
});
};
console.log(check('3'))
Run Code Online (Sandbox Code Playgroud) (打印x)打印出我想要的eval,但是(eval x)失败,但如果我运行x它就可以了!我错过了什么?
请告诉我为什么这不起作用,或者我做了一些愚蠢的事情.
我正在尝试打印动态大小的表并设置lambda变量,以最终评估表中每个单元格的表达式.
顺便说一句我弄清楚为什么eval失败了.(eval x)正在丢失宏,但是为什么?!
这有效:
(defvar varlist '(a b c d))
(defvar vvars '(c d))
(defvar hvars '(a b))
(macrolet ((AlternateVariable (var &rest body)
`(dolist (,var '(nil t)) ,@body))
(AlternateVariables (varlist &rest body)
(if (null varlist)
(cons 'progn body)
`(AlternateVariable ,(car varlist)
(AlternateVariables ,(cdr varlist) ,@body)))))
(let ((listvarlist (cons 'list varlist)))
(print
`(AlternateVariables ,(reverse vvars)
(AlternateVariables ,(reverse hvars)
(format t "row=~S~%" ,listvarlist) ))))
nil)
Run Code Online (Sandbox Code Playgroud)
它打印出我想要的东西:
(alternatevariables (d c)
(alternatevariables (b a) (format t "row=~S~%" (list a b c …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个宏,它将在Clojure中捕获编译时错误.具体来说,我想捕获当调用并clojure.lang.Compiler$CompilerException抛出一个尚未针对该数据类型实现的协议方法时抛出的异常.
到目前为止,我有:
(defmacro catch-compiler-error
[body]
(try
(eval body)
(catch Exception e e)))
但当然,我被告知这eval是邪恶的,你通常不需要使用它.有没有办法实现这个而不使用eval?
我倾向于认为这eval是合适的,因为我特别希望在运行时而不是在编译时评估代码.