在过去的几个月里,我一直在学习很多关于JavaScript的知识.多年来一直滥用语言,我敢说我现在对语言有了更好的理解,并且我开始喜欢它的功能性.
最近我接受了学习计划,但这只是为了好玩.浏览MDN引用我注意到JS虽然缺少块作用域,但确实有一个关键字可用于声明给定块的本地变量,就像Scheme的一样let:
for (var i=0;i<someArray.length;i++)
{
console.log(someArray[i]);
}
console.log(i);//will log someArray's length
Run Code Online (Sandbox Code Playgroud)
鉴于:
for (let i=0;i<someArray.length;i++)
{
console.log(someArray[i]);
}
console.log(i);//undefined
Run Code Online (Sandbox Code Playgroud)
所以我现在想知道的是:为什么不let经常使用?它与X浏览器支持有关吗?它只是那些鲜为人知的好东西之一吗?
简而言之,使用var过有let什么好处,有什么警告?
据我所知,行为let是,如果有的话,更一致(单个块中的双重声明引发一个TypeError,除了函数体(ECMA6草稿修复了这个).
说实话,除了这个功能/关键字我不是很了解,我很难想到任何反对使用letfor循环的论据,或者临时变量使代码更易读的地方.
我有一些不理解来自gnu clisp的动作假设,我有一些代码 (let ((x "Hi!"))(print x)).如果我从控制台执行它(比如,clisp fileName.lisp),我明白了
嗨!
但是,当我从解释器执行它时,我会看到这个文本两次.为什么?
请帮帮我.
在我向一个不熟悉clojure的同事解释一些clojure代码之前,我从未真正考虑过这个问题.let当他问你为什么使用向量来声明绑定而不是列表时,我向他解释.我对他没有真正的答案.但该语言确实限制您使用列表:
=> (let (x 1) x)
java.lang.IllegalArgumentException: let requires a vector for its binding (NO_SOURCE_FILE:0)
Run Code Online (Sandbox Code Playgroud)
这究竟是为什么?
我意识到这可能是一个愚蠢的问题,但......
如果我链接了一堆let里面做陈述并不需要知道对方的价值观,是它更好地使用and或in?
例如,如果有的话,哪一个更可取:
let a = "foo"
and b = "bar"
and c = "baz"
in
(* etc. *)
Run Code Online (Sandbox Code Playgroud)
要么
let a = "foo" in
let b = "bar" in
let c = "baz"
in
(* etc. *)
Run Code Online (Sandbox Code Playgroud)
我的直觉告诉我,前者应该"更好"(通过对"更好"的非常小的定义),因为它创造了必要的最小范围,而后者是范围内的范围.编译器/解释器注意的范围,但最终是不重要和不必要的深度.
我有一些麻烦,想知道如何使用"让"形式.在下面的示例中,我想在本地绑定值"cols",以便稍后在函数中处理它.然而,我注意到的是,如果我使用"let"函数,则sel-opt-tmp函数将返回nil值而不是列表.
(defn sel-opt-tmp []
(let [cols "test"]))
(prn (sel-opt-tmp))
Run Code Online (Sandbox Code Playgroud)
*上面的代码返回一个nil值.
我理解"let"只绑定函数范围内的值,我不知道是否有办法将值传递给let范围.也许有一些我不知道的"回归"?或者这只是糟糕的设计,在这种情况下我根本不应该使用绑定(这往往会创建很长的函数链,尽管很难读)?
在Haskell教程中,我遇到了以下代码:
do [...]
let atom = [first] ++ rest
return $ case atom of
Run Code Online (Sandbox Code Playgroud)
请注意,let表达式没有in块.这种let表达的范围是什么?下一行?
我可以看到两种实现let绑定的方法.首先,如从SICP所知,let可以实现为lambda函数.这是方便和简单的,但考虑到每个lambda(fn)在JVM中被转换为单独的类并且let在平均程序中使用的次数这一事实,这看起来非常非常昂贵.
其次,let绑定可以直接转换为本地Java变量.这会产生很少的开销,但是在堆栈上存储绑定会破坏语言语义:在这种情况下,创建闭包是不可能的 - 保存的值将在堆栈展开后立即销毁.
那么Clojure中使用的实际实现是什么?指出Clojure源中的相应行是值得赞赏的.
我有这样的代码:
var list = new List<int> {1, 2, 3, 4, 5};
var result = from x in list.AsParallel()
let a = LongRunningCalc1(x)
let b = LongRunningCalc2(x)
select new {a, b};
Run Code Online (Sandbox Code Playgroud)
让我们说LongRunningCalc每种方法需要1秒钟.上面的代码大约需要2秒才能运行,因为虽然5个元素的列表是并行操作的,但是从let语句中调用的两个方法是按顺序调用的.
但是,这些方法也可以安全地并行调用.他们显然需要合并回来,select但直到那时应该并行运行 - select应该等待它们.
有没有办法实现这个目标?
我想使用变量的值来计算同一let语句中另一个变量的值.有没有办法在Clojure中执行此操作而不使用嵌套的let?
嵌套让解决方案:
(let [x 3]
(let [y (+ 1 x)]
y)) = 4
Run Code Online (Sandbox Code Playgroud)
期望的解决方案:
(let [x 3
y (+ 1 x)]
y) = 4
Run Code Online (Sandbox Code Playgroud) 在这次讨论 布赖恩·马里克使得该点let并for有单子Clojure中:
也就是说,真正通用的monad倾向于以特殊形式写入语言.Clojure是
let和formonad,但你不需要知道使用它们.
这是 let
user=> (let [c (+ 1 2)
[d e] [5 6]]
(-> (+ d e) (- c)))
8
Run Code Online (Sandbox Code Playgroud)
这是 for
user=> (for [x [0 1 2 3 4 5]
:let [y (* x 3)]
:when (even? y)]
y)
(0 6 12)
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么Clojure let和for两个monad?