我发现以下是一个坏主意,原因很多.我也意识到,鉴于我有一个23的stackoverflow代表,它的本质是假设我是一个新手学习编程.但是,请幽默我,并专注于"我们怎么做",而不是"你为什么要这样做/你不想这样做"的方面.
我想要的是:
(def dog (Dog. ...))
(def cat (Cat. ...))
(with-animal dog
(println (str "Dog: " (speak) "\n")))
(with-animal cat
(println (str "Cat: " (speak) "\n")))
Run Code Online (Sandbox Code Playgroud)
输出:
Dog: woof
Cat: meow
Run Code Online (Sandbox Code Playgroud)
所以基本上,我希望with-animal是一个宏,所有出现的"speak"函数调用都会被映射到我正在调用块的对象.
特别是,我不想写:
(let-binding [speak (fn [] "woof")] ...)
(let-binding [speak (fn [] "meow")] ...)
Run Code Online (Sandbox Code Playgroud)
相反,我希望with-animal将speak函数映射到我正在调用的对象的某个方法.
在Clojure中有一个干净的方法吗?
谢谢!
我看了参考文献:http://clojure.org/vars#Vars%20and%20the%20Global%20Environment,http://clojuredocs.org/clojure_core/clojure.core/binding
我仍然不明白为什么总是需要,binding因为我写的每个程序都没有它们,我可以找到以常规方式编写示例的方法 - 我觉得这更容易理解.有没有使用这个的项目/编程范例的例子?
例如......在动物说话例子中,你可以得到类似的效果:
(def dog {:name "Dog" :sound "Woof"})
(def cat {:name "Cat" :sound "Meow"})
(defn speak [animal]
(str (:name animal) " says " (:sound animal))
(println (speak dog))
(println (speak cat))
Run Code Online (Sandbox Code Playgroud)
没有宏,没有动态绑定......还是很干净.
我想我理解为什么在使用动态范围的语言中允许闭包存在危险.也就是说,似乎你可以关闭变量OK,但是当你尝试读取它时,你只能得到全局堆栈顶部的值.如果其他功能在过渡期间使用相同的名称,这可能会很危险.
我是否错过了其他一些微妙之处?
有问题的性别是
(((lambda (b)
(lambda (a)
(+ b a))) 3) 5)
Run Code Online (Sandbox Code Playgroud)
对我来说,它看起来应该评估8,并且在其他lisps(例如Racket)中它确实如此,但在elisp中它反而抛出了这个错误:
Debugger entered--Lisp error: (invalid-function ((lambda (b) (lambda (a) (+ b a))) 3))
Run Code Online (Sandbox Code Playgroud)
它似乎在告诉我
((lambda (b)
(lambda (a)
(+ b a))) 3)
Run Code Online (Sandbox Code Playgroud)
不是有效的功能.这似乎是错误的,因为当我评估那个表达式时,我得到了
(lambda (a) (+ b a))
Run Code Online (Sandbox Code Playgroud)
这看起来对我来说是一个有效的功能.有谁知道为什么会这样?它与动态范围有关吗?
我正在寻找并在indir实施中看到这个评论:
sub indir(Str() $path, $what, :$test = <r w>) {
my $newCWD := $*CWD.chdir($path,:$test);
$newCWD // $newCWD.throw;
{
my $*CWD = $newCWD; # temp doesn't work in core settings :-(
$what();
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这种使用my很奇怪,这导致了文档问题#1082,如果my实际上是词汇,那就傻笑了.我原以为这temp对于动态变量的用户级临时更改更合适.
但是现在,我看到了这个评论,但我不太清楚这意味着什么.被temp打破这么深?这里没有吗?或者评论错了吗?
如果评论是正确的,那么这种处理动态变量的方式是否已经泄露到日常程序员级别,因为这是一些人必须做的事情(他们习惯了吗?)
而且,这个级别真的有多低?似乎所有的Perl 6都应该可以在这里找到.
以下emacs lisp文件是关于当Alice foo在她的init文件中使用词法绑定的局部变量并且Bob 在他的init文件中定义foo为全局特殊变量defvar并且Alice将Bob的init文件代码的一部分借入她自己的init文件时发生的事情.知道这foo会变得特别.
;; -*- lexical-binding: t; -*-
;; Alice init file
;; Alice defining alice-multiplier
(defun alice-multiplier-1 (foo)
(lambda (n) (* n foo)))
(defun alice-multiplier-2 (num)
(let ((foo num))
(lambda (n) (* n foo))))
;; Alice using alice-multiplier
(print
(list
:R1 (mapcar (alice-multiplier-1 10) (list 1 2 3))
:R2 (mapcar (alice-multiplier-2 10) (list 1 2 3))))
;; from Bob's code
;; ...
(defvar foo 1000)
;; ...
;; Alice using alice-multiplier …Run Code Online (Sandbox Code Playgroud) 所以我有这个问题,我必须使用两个不同的范围规则来计算输出.我知道用词汇范围输出a=3和b=1,但我使用动态范围界定有很难弄清楚输出.
注意:下面的代码示例使用C语法,但我们只是将其视为伪代码.
int a,b;
int p() {
int a, p;
a = 0; b = 1; p = 2;
return p;
}
void print() {
printf("%d\n%d\n",a,b);
}
void q () {
int b;
a = 3; b = 4;
print();
}
main() {
a = p();
q();
}
Run Code Online (Sandbox Code Playgroud)
这是我想出来的.使用动态范围,非本地引用a和b可以更改.所以我有a=2(从p()返回,然后b=4(在q()内).那么输出是2 4?
根据我的经验,很少/永远不需要设置scope="request"EL变量.
例如,我有一个页面,给定一个item参数,根据其属性构造一个特定于该项目的URL.此页面包含在需要呈现项目链接的任何页面中.
<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
<c:when test="${empty urlTemplate}">
<c:set var="itemUrl" scope="request" value="/missingProductUrl.jsp"/>
</c:when>
<c:otherwise>
<c:url var="itemUrl" scope="request" value="${urlTemplate}">
<c:param name="id" value="${param['item'].id}"/>
</c:url>
</c:otherwise>
</c:choose>
Run Code Online (Sandbox Code Playgroud)
<jsp:include page="itemLink.jsp">
<jsp:param name="item" value="${currentItem}"/>
</jsp:include>
<%-- 'itemUrl' has request scope --%>
<a href="${itemUrl}">Item Link</a>
Run Code Online (Sandbox Code Playgroud)
<%-- Accepts a parameter named 'item' --%>
<c:set var="urlTemplate" value="${param['item'].urlTemplate}" />
<c:choose>
<c:when test="${empty urlTemplate}">
<c:set var="itemUrl" value="/missingProductUrl.jsp"/>
</c:when>
<c:otherwise>
<c:url var="itemUrl" value="${urlTemplate}"> …Run Code Online (Sandbox Code Playgroud) 在尝试解决与宏变量范围相关的问题时,我发现了这个非常有用的SO页面. 为什么不让%创建一个本地宏变量?
总而言之,写作%let x = [];或%do x = [] %to [];宏观将:
这让我觉得非常不直观.我愿意打赌,由于这种设计选择,SAS荒野中有大量的漏洞.我很少在宏中看到%local语句,甚至在使用常见变量名称(如"i"或"counter")的循环语句之上.例如,我刚从SUGI和SAS全球论坛论文http://www.lexjansen.com/cgi-bin/xsl_transform.php?x=sgf2015&c的标题中提取了标题为"宏"的第一篇论文 . =杉
事实上,我在我开的第一份SAS会议论文中找到了这段代码:
%macro flag;
data CLAIMS;
set CLAIMS;
%do j= 1 %to 3;
if icd9px&j in (&codelist)
then _prostate=1;
%end;
run;
%mend;
%flag;
Run Code Online (Sandbox Code Playgroud)
http://support.sas.com/resources/papers/proceedings15/1340-2015.pdf
任何一个叫%flag并且有自己的&j变量的人都有祸了.他们很容易最终没有日志错误,但结果是假的,因为他们的&j在他们调用%flag之后到处都是4,这将是(来自经验)一个跟踪没有乐趣的错误.或者更糟糕的是,他们可能永远不会认识到他们的结果是假的.
所以我的问题是,为什么决定不将所有宏变量默认为本地范围?SAS宏变量范围的工作原理是否有充分的理由?
我正在阅读Hadley的AdvancedR,并在此URL上测试以下代码
subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
condition = 3
subset2(df, a < condition)
Run Code Online (Sandbox Code Playgroud)
然后我收到以下错误消息:
eval中的错误(替换(条件),df):找不到对象'a'
我阅读的解释如下,但不太明白:
如果eval()无法在数据框(第二个参数)中找到变量,则它会查找subset2()的环境.这显然不是我们想要的,所以我们需要一些方法告诉eval()在哪里查看它是否找不到数据框中的变量.
在我看来,虽然"eval(替代(条件),df)",他们找不到的变量是条件,那么为什么无法找到对象"a"?
另一方面,为什么下面的代码不会出错?
subset2 = function(df, condition){
condition_call = eval(substitute(condition),df )
df[condition_call,]
}
df = data.frame(a = 1:10, b = 2:11)
y = 3
subset2(df, a < y)
Run Code Online (Sandbox Code Playgroud)