我编写了一个小的Haskell程序来打印当前目录中所有文件的MD5校验和(递归搜索).基本上是Haskell版本的md5deep.一切都很好,花花公子,除非当前目录有大量的文件,在这种情况下,我收到如下错误:
<program>: <currentFile>: openBinaryFile: resource exhausted (Too many open files)
Run Code Online (Sandbox Code Playgroud)
似乎Haskell的懒惰导致它不会关闭文件,即使在相应的输出行已经完成之后也是如此.
相关代码如下.感兴趣的功能是getList.
import qualified Data.ByteString.Lazy as BS
main :: IO ()
main = putStr . unlines =<< getList "."
getList :: FilePath -> IO [String]
getList p =
let getFileLine path = liftM (\c -> (hex $ hash $ BS.unpack c) ++ " " ++ path) (BS.readFile path)
in mapM getFileLine =<< getRecursiveContents p
hex :: [Word8] -> String
hex = concatMap (\x -> printf "%0.2x" …Run Code Online (Sandbox Code Playgroud) 是否可以(*)在Haskell中实现最严格的语义(标准化的Haskell首选,但扩展是可以的.使用编译器内部是作弊)?例如,这样的定义应该导致以下情况:
0 * ? = 0
? * 0 = 0
Run Code Online (Sandbox Code Playgroud)
并且只有:
? * ? = ?
Run Code Online (Sandbox Code Playgroud)
我可以构建满足上述情况之一但不能同时满足这两种情况的模式匹配,因为零检查会强制该值.
我想知道初始化类成员的python方法是什么,但只有在访问它时才会访问它.我尝试了下面的代码并且它正在运行,但有什么比这简单吗?
class MyClass(object):
_MY_DATA = None
@staticmethod
def _retrieve_my_data():
my_data = ... # costly database call
return my_data
@classmethod
def get_my_data(cls):
if cls._MY_DATA is None:
cls._MY_DATA = MyClass._retrieve_my_data()
return cls._MY_DATA
Run Code Online (Sandbox Code Playgroud) 我正在寻找一个Haskell编译器,它默认使用严格的评估而不是延迟评估.我只想使用OCaml,但Haskell的语法比OCaml 好得多(而且Haskell是纯粹的,并且具有很酷的功能,比如类型类).
我真的宁愿不经常把!s和$!s全部放在我的程序上.带有开关或预处理器的编译器可以输入严格的注释,这非常好.如果有一种方法在某些地方使用延迟评估也是有帮助的,以防万一我想要无限列表(我可能永远不会).
请不要试图说服懒惰的评价更好,我真的需要表现.IIRC,西蒙佩顿琼斯甚至说,懒惰的评价是不是真的有必要,它在那里主要是为了防止他们的语言不纯.
在Python(和其他)中,您可以通过在函数中使用'yield'运算符来递增地处理大量数据.在PHP中以类似的方式做什么?
例如,假设在Python中,如果我想读取一个可能非常大的文件,我可以一次一行地处理每一行(这个例子是设计的,因为它与'for file in file_obj基本相同) "):
def file_lines(fname):
f = open(fname)
for line in f:
yield line
f.close()
for line in file_lines('somefile'):
#process the line
Run Code Online (Sandbox Code Playgroud)
我现在正在做的(在PHP中)是我正在使用私有实例变量来跟踪状态,并且每次调用函数时都会相应地执行操作,但似乎必须有更好的方法.
我无法理解这段代码:
let
sieve (p:xs) = p : sieve (filter (\ x -> x `mod` p /= 0) xs)
in sieve [2 .. ]
Run Code Online (Sandbox Code Playgroud)
有人可以为我分手吗?我知道它有递归,但这就是问题我无法理解这个例子中的递归是如何工作的.
在Clojure编程语言中,为什么这段代码会以绚丽的色彩传递?
(let [r (range 1e9)] [(first r) (last r)])
Run Code Online (Sandbox Code Playgroud)
虽然这个失败了:
(let [r (range 1e9)] [(last r) (first r)])
Run Code Online (Sandbox Code Playgroud)
我知道这是关于"失去理智"的建议,但请你解释一下吗?我还没能消化它.
更新:
真的很难找到正确的答案,两个答案是惊人的信息.
注意:代码片段来自"Clojure的喜悦".
functional-programming clojure jvm-languages lazy-evaluation
我一直在使用Data.Binary将数据序列化为文件.在我的应用程序中,我逐步向这些文件添加项目.两个最流行的序列化包,二进制和谷物,两个序列化列表作为计数后跟列表项.因此,我无法附加到我的序列化文件.我目前读取整个文件,反序列化列表,附加到列表,重新序列化列表,并将其写回文件.但是,我的数据集越来越大,我开始耗尽内存.我可以绕过拆箱我的数据结构以获得一些空间,但这种方法不能扩展.
一种解决方案是使文件格式下降和更改以更改初始计数,然后只需附加我的元素.但这并不令人满意,更不用说由于打破抽象而对文件格式的未来变化敏感.Iteratees/Enumerators在这里成为一个有吸引力的选择.我找了一个库,将它们与二进制序列化相结合,但没有找到任何东西.有谁知道这是否已经完成?如果没有,那么这个库是否有用?或者我错过了什么?
我的背景是生物信息学,特别是新一代测序,但问题是通用的; 所以我将使用日志文件作为示例.
该文件非常大(千兆字节大,压缩,因此它不适合内存),但很容易解析(每行都是一个条目),所以我们可以轻松地写出如下内容:
parse :: Lazy.ByteString -> [LogEntry]
Run Code Online (Sandbox Code Playgroud)
现在,我有很多我想从日志文件中计算的统计信息.编写单独的函数是最简单的,例如:
totalEntries = length
nrBots = sum . map fromEnum . map isBotEntry
averageTimeOfDay = histogram . map extractHour
Run Code Online (Sandbox Code Playgroud)
所有这些都是这种形式foldl' k z . map f.
问题是,如果我尝试以最自然的方式使用它们,比如
main = do
input <- Lazy.readFile "input.txt"
let logEntries = parse input
totalEntries' = totalEntries logEntries
nrBots' = nrBots logEntries
avgTOD = averageTimeOfDay logEntries
print totalEntries'
print nrBots'
print avgTOD
Run Code Online (Sandbox Code Playgroud)
这会将整个列表分配到内存中,这不是我想要的.我希望折叠同步完成,以便可以对垃圾收集进行垃圾收集.如果我只计算一个统计量,就会发生这种情况.
我可以写一个这样做的大函数,但它是不可组合的代码.
或者,这就是我一直在做的,我分别运行每个传递,但每次重新加载和解压缩文件.
我有一个像这样的表达式/公式
std::string expr="((A>0) && (B>5 || C > 10))";
Run Code Online (Sandbox Code Playgroud)
我做了一些研究,似乎如果已知A,B,C值,通过在C++程序中嵌入Lua或Python,有些eval函数可以替代A,B和C并返回true或false.
但是当我不知道所有的价值时会发生什么?让我们说A是已知的,它是-1.如果A为-1,则无论B或C的值如何,公式都将评估为"假".
我可以在不事先知道所有变量的情况下评估公式吗?例如,如果A为10,则查找B的值并再次重新评估是有意义的.我们如何解决这些问题?想法?