我是一名中级Haskell程序员,拥有严格的FP和非FP语言方面的丰富经验.我的大多数Haskell代码都分析了中等大小的数据集(10 ^ 6..10 ^ 9个东西),因此懒惰总是潜伏着.我对thunks,WHNF,模式匹配和分享有相当好的理解,并且我已经能够用爆炸模式和seq修复泄漏,但这种轮廓和祈祷方法感觉肮脏和错误.
我想知道经验丰富的Haskell程序员在设计时如何处理懒惰.我不是在询问像Data.ByteString.Lazy或foldl'这样的简单项目; 相反,我想知道你如何看待导致运行时内存问题和棘手调试的低级懒惰机器.
在设计时如何看待thunks,模式匹配和共享?
您使用什么样的设计模式和习惯来避免泄漏?
你是如何学习这些模式和习语的,你有一些好的参考资料吗?
您如何避免过早优化非泄漏的非问题?
(2014-05-15修订时间预算):
您是否预算了大量项目时间来查找和修复内存问题?
或者,您的设计技巧通常可以避免内存问题,并且您在开发周期的早期阶段就可以获得预期的内存消耗吗?
我有一个Django表单,我在正常的Django视图中进行验证.我试图找出如何提取纯错误(没有HTML格式).下面是我目前正在使用的代码.
return json_response({ 'success' : False,
'errors' : form.errors })
Run Code Online (Sandbox Code Playgroud)
有了这个,我从Django得到了臭名昭着的代理对象错误.将每个错误强制转换为Unicode也不会起作用,因为这样__unicode__就可以有效地调用每个错误的方法.
有任何想法吗?
编辑:
对于那些感兴趣的人,这是定义json_response:
def json_response(x):
import json
return HttpResponse(json.dumps(x, sort_keys=True, indent=2),
content_type='application/json; charset=UTF-8')
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个简单的筛子函数来计算clojure中的素数.我已经看到了这个关于编写高效的筛分功能的问题,但我不是为了那点呢.现在我只想写一个非常简单(缓慢)的筛子.以下是我的想法:
(defn sieve [potentials primes]
(if-let [p (first potentials)]
(recur (filter #(not= (mod % p) 0) potentials) (conj primes p))
primes))
Run Code Online (Sandbox Code Playgroud)
对于小范围,它工作正常,但导致堆栈溢出大范围:
user=> (sieve (range 2 30) [])
[2 3 5 7 11 13 17 19 23 29]
user=> (sieve (range 2 15000) [])
java.lang.StackOverflowError (NO_SOURCE_FILE:0)
Run Code Online (Sandbox Code Playgroud)
我认为通过使用recur这将是一个非堆栈消耗循环结构?我错过了什么?
我有一个包含以下内容的类:
public static class Config
{
private static Lazy<ConfigSource> _cfgSrc = new Lazy<ConfigSource>(
() => { /* "ValueFactory" here... */ },
true);
public static ConfigSource ConfigSource
{
get { return _cfgSrc.Value; }
}
}
Run Code Online (Sandbox Code Playgroud)
在访问该ConfigSource属性时,我遇到了这个InvalidOperationException:
ValueFactory尝试访问此实例的Value属性.
我在访问该Value属性的"值工厂"方法中看不到任何内容.还有什么可以触发这个例外吗?此问题只是间歇性地发生,但一旦发生,它需要重置IIS以清除异常(一旦发生就会缓存).
在C++中编写这样的代码时:
bool allTrue = true;
allTrue = allTrue && check_foo();
allTrue = allTrue && check_bar();
Run Code Online (Sandbox Code Playgroud)
check_bar()如果check_foo()退回,将不会被评估false.这称为短路或短路评估,是惰性评估原则的一部分.
这是否适用于复合赋值运算符&=?
bool allTrue = true;
allTrue &= check_foo();
allTrue &= check_bar(); //what now?
Run Code Online (Sandbox Code Playgroud)
用逻辑OR替换所有&with |和truewith false.
c++ boolean lazy-evaluation short-circuiting compound-assignment
.NET 4.0中有一个很好的新方法,可以通过枚举以流方式获取目录中的文件.
这里的问题是,如果想要枚举所有文件,可能事先不知道哪些文件或文件夹受到访问保护并且可能抛出UnauthorizedAccessException.
要重现,可以运行此片段:
foreach (var file in Directory.EnumerateFiles(@"c:\", "*", SearchOption.AllDirectories))
{
// whatever
}
Run Code Online (Sandbox Code Playgroud)
在此.NET方法存在之前,通过在字符串数组返回方法上实现递归迭代器,可以实现大致相同的效果.但它并不像新的.NET方法那么懒惰.
那么该怎么办?使用此方法时,UnauthorizedAccessException可以被抑制还是生活中的事实?
在我看来,该方法应该有一个重载接受一个动作来处理任何异常.
在来自解析器组合器库的文件Parsers.scala(Scala 2.9.1)中,我似乎遇到了一个鲜为人知的Scala功能,称为"懒惰参数".这是一个例子:
def ~ [U](q: => Parser[U]): Parser[~[T, U]] = { lazy val p = q // lazy argument
(for(a <- this; b <- p) yield new ~(a,b)).named("~")
}
Run Code Online (Sandbox Code Playgroud)
显然,这里有一些事情正在q为lazy val 分配call-by-name参数p.
到目前为止,我还没有弄清楚它的作用以及为什么它有用.有人可以帮忙吗?
我是Ruby的新手,有没有办法yield从Ruby函数中获取值?如果有,怎么样?如果没有,我有什么选择来编写惰性代码?
经过几个小时的调试,我意识到一个非常简单的玩具示例由于缺少!表达式而效率不高return $ 1 + x(感谢 duplode!...但是 ghc 怎么不优化它??)。我也意识到了这一点,因为我将它与更快的 Python 代码进行比较,但我不会总是编写 Python 代码来对我的代码进行基准测试......
所以这是我的问题:有没有办法自动检测这些“懒惰的内存泄漏”,这会无缘无故地减慢程序的速度?我在优化 Haskell 代码方面仍然很糟糕,而且!很可能会忘记 a ,即使您有经验,我猜也是如此。
我知道:
+RTS -s,但我不知道如何解释它:看到79MB的内存为一个简单的程序似乎是巨大的,以我为例子,但也许它不是因为它是什么把我目前的计划......而更大的计划,这是不可能,只是检测我猜是这样的“惰性泄漏”,因为我不知道我的程序应该占用多少内存。cabal v2-run --enable-profiling mysatsolvers -- +RTS -p命令,但似乎使探查杀死由GHC做了一些优化技术,因此它很难使用这些值,真正的标杆。而且,我仍然不清楚如何从该输出中找到泄漏。例如,您能否向我解释如何在这样的玩具程序中找到“懒惰的泄漏”?
{-# LANGUAGE DerivingVia, FlexibleInstances, ScopedTypeVariables #-}
module Main where
--- It depends on the transformers, containers, and base packages.
--- Optimisation seems to be important or the NoLog case will be way to long.
--- $ ghc -O Main.hs
import …Run Code Online (Sandbox Code Playgroud) 我正在消化这个精彩的演示文稿为什么要学习Haskell?作者:Keegan McAllister.他在那里使用了片段
minimum = head . sort
Run Code Online (Sandbox Code Playgroud)
作为Haskell懒惰评估的一个例子,说明在Haskell中minimum有时间复杂度 O(n).但是,我认为这个例子具有学术性质.因此,我要求一个更实际的例子,即大多数中间计算都被抛弃,这并不是显而易见的.
lazy-evaluation ×10
haskell ×3
memory-leaks ×2
.net ×1
.net-4.0 ×1
boolean ×1
c# ×1
c++ ×1
clojure ×1
django ×1
django-forms ×1
filesystems ×1
json ×1
optimization ×1
primes ×1
recursion ×1
ruby ×1
scala ×1
unicode ×1