标签: lazy-evaluation

Haskell中的懒惰和尾部递归,为什么会崩溃?

我有这个相当简单的函数来计算大列表元素的平均值,使用两个累加器来保存到目前为止的总和以及到目前为止的计数:

mean = go 0 0
    where
      go s l []     = s / fromIntegral l
      go s l (x:xs) = go (s+x) (l+1) xs

main = do
  putStrLn (show (mean [0..10000000]))
Run Code Online (Sandbox Code Playgroud)

现在,用严格的语言,这将是尾递归,并且没有问题.然而,由于Haskell很懒,我的谷歌搜索让我明白(s + x)和(l + 1)将作为thunk传递递归.所以整件事崩溃和烧伤:

Stack space overflow: current size 8388608 bytes.
Run Code Online (Sandbox Code Playgroud)

进一步的谷歌搜索后,我发现seq$!.这似乎我不理解,因为我在这种情况下使用它们的所有尝试都证明是徒劳的,错误信息说的是关于无限类型的东西.

最后我发现-XBangPatterns,它通过改变递归调用来解决所有问题:

go !s !l (x:xs) = go (s+x) (l+1) xs
Run Code Online (Sandbox Code Playgroud)

但我对此并不满意,因为-XBangPatterns目前这是一个扩展.我想知道如何在不使用的情况下严格评估-XBangPatterns.(也许还可以学到一些东西!)

只是让你理解我缺乏理解,这就是我尝试过的(编译的唯一尝试,即):

go s l (x:xs) = go (seq s (s+x)) (seq l (l+1)) xs …
Run Code Online (Sandbox Code Playgroud)

optimization performance haskell lazy-evaluation ghc

18
推荐指数
3
解决办法
3057
查看次数

Ruby中的懒惰评估

我有一个Ruby的情况,可能需要创建一个对象,但它不确定.由于对象的创建可能代价高昂,因此我并不急于创建它.我认为这是延迟加载的明显案例.如何定义仅在有人向其发送消息时才创建的对象?该对象将在块中创建.有没有办法在Ruby中进行简单的延迟加载/初始化?这些东西是否支持这些东西,它们为各种懒惰的对象初始化提供了不同的解决方案?谢谢你的建议!

ruby lazy-loading lazy-evaluation

18
推荐指数
2
解决办法
2万
查看次数

Hibernate:在HQL中覆盖映射的EAGER?

可以LAZY使用HQL 覆盖LEFT JOIN FETCH.

FROM Obj AS obj LEFT JOIN FETCH obj.otherObj WHERE obj.id = :id
Run Code Online (Sandbox Code Playgroud)

是否也可以覆盖EAGER?怎么样?

hibernate hql eager lazy-evaluation fetch

18
推荐指数
2
解决办法
1万
查看次数

PHP短路延迟评估,它在php.net手册中的位置?

很抱歉,这听起来像是一个非常愚蠢的问题.

但我用Google搜索了网络,并专门搜索了php.net网站和stackoverflow.com网站. 我知道PHP在使用and, or, &&, ||运算符时会进行短路延迟评估,但在PHP手册中它的声明清晰明了?

我发现只有维基百科是唯一的'可信'来源,它说PHP对这些运营商进行了懒惰的评估.

php lazy-evaluation short-circuiting

18
推荐指数
1
解决办法
5864
查看次数

Haskell的mapM不是懒惰吗?

更新:好的,这个问题可能非常简单.

q <- mapM return [1..]
Run Code Online (Sandbox Code Playgroud)

为什么这永远不会回来?


mapM是不是懒得处理无限列表?

下面的代码挂起.但是,如果我用线B替换A线,它就不会再挂起了.或者,如果我在A行之前加上"splitRandom $",它也不会挂起.

Q1是:mapM不是懒惰的吗?否则,为什么用线B替换A行"修复此"代码?

Q2是:为什么前面的A行与splitRandom"解决"了这个问题?

import Control.Monad.Random
import Control.Applicative

f :: (RandomGen g) => Rand g (Double, [Double])
f = do
    b <- splitRandom $ sequence $ repeat $ getRandom
    c <- mapM return b -- A
    -- let c = map id b -- B
    a <- getRandom
    return (a, c)

splitRandom :: (RandomGen g) => Rand g a -> Rand g a
splitRandom code = evalRand code <$> getSplit

t0 …
Run Code Online (Sandbox Code Playgroud)

monads haskell lazy-evaluation

18
推荐指数
3
解决办法
2961
查看次数

在Clojure中编写一个惰性的,功能性的,交互式的命令行应用程序

我想知道:编写与用户或其他程序通过stdin和stdout交互的Clojure程序的最佳方法是什么?

显然,有可能编写某种命令式循环,但我希望找到一些更懒惰/功能的东西,有点受Haskell的"交互"功能的启发.

command-line functional-programming interactive clojure lazy-evaluation

18
推荐指数
1
解决办法
698
查看次数

Haskell中的空间泄漏

我已多次读过Haskell中的懒惰评估有时会导致空间泄漏.什么样的代码会导致空间泄漏?如何检测它们?并且程序员可以采取哪些预防措施来避免它们?

haskell functional-programming lazy-evaluation space-leak

18
推荐指数
1
解决办法
3026
查看次数

什么时候不安全InterteraveIO不安全?

不像其他不安全*操作,文档unsafeInterleaveIO是不是其可能存在的缺陷非常明显的.那么到底什么时候不安全?我想知道并行/并发和单线程使用的条件.

更具体地说,以下代码中的两个函数在语义上是等价的吗?如果没有,何时以及如何?


joinIO :: IO a -> (a -> IO b) -> IO b
joinIO  a f = do !x  <- a
                    !x'  <- f x
                    return x'

joinIO':: IO a -> (a -> IO b) -> IO b
joinIO' a f = do !x  <- unsafeInterleaveIO a
                    !x' <- unsafeInterleaveIO $ f x
                    return x'
Run Code Online (Sandbox Code Playgroud)

以下是我在实践中如何使用它:


data LIO a = LIO {runLIO :: IO a}

instance Functor LIO where
  fmap f (LIO a) = LIO …
Run Code Online (Sandbox Code Playgroud)

haskell lazy-evaluation ghc

18
推荐指数
2
解决办法
2339
查看次数

何时严格评估Haskell?

据我所知!(称为bangs)用于表示应严格评估表达式.但对于我来说,将它们放在哪里或者根本不是那么明显.

import qualified Data.Vector.Unboxed as V

main :: IO ()
main = print $ mean (V.enumFromTo 1 (10^9))

mean :: V.Vector Double -> Double
Run Code Online (Sandbox Code Playgroud)

不同版本的意思是:

-- compiled with O2 ~ 1.14s
mean xs = acc / fromIntegral len
    where !(len, acc)    = V.foldl' f (0,0) xs :: (Int, Double)
          f (len, acc) x = (len+1, acc+x)

-- compiled with O2 ~ 1.18s
mean xs = acc / fromIntegral len
    where (!len, !acc)   = V.foldl' f (0,0) xs :: …
Run Code Online (Sandbox Code Playgroud)

optimization performance haskell lazy-evaluation

18
推荐指数
2
解决办法
1048
查看次数

Kotlin:延迟到val,或者是一个可以设置一次的var

只是好奇:在Kotlin中,我很想得到一些可以通过懒惰来初始化的val,但是有一个参数.那是因为我需要为了初始化它而创建的东西很晚.

具体来说,我希望我有:

private lateinit val controlObj:SomeView
Run Code Online (Sandbox Code Playgroud)

要么:

private val controlObj:SomeView by lazy { view:View->view.findViewById(...)}
Run Code Online (Sandbox Code Playgroud)

然后:

override fun onCreateView(....) {
    val view = inflate(....)


    controlObj = view.findViewById(...)
Run Code Online (Sandbox Code Playgroud)

或在第二种情况下controlObj.initWith(view)或类似的情况:

return view
Run Code Online (Sandbox Code Playgroud)

我无法使用,by lazy因为by lazy初始化时不会接受外部参数.在这个例子中 - 包含view.

当然我有,lateinit var但如果我能确保它在设置后变为只读,我会在一行中完成它会很好.

是否有一种非常干净的方法来创建只读初始化一次的只读变量,但只有当其他变量出生时?任何init once关键字?在init之后,编译器知道它是不可变的?

我知道这里存在潜在的并发问题,但如果我敢于在init之前访问它,我当然应该被抛出.

android immutability lazy-evaluation kotlin kotlin-lateinit

18
推荐指数
3
解决办法
6845
查看次数