天天看点

python中and和or的惰性求值特点_Haskell中的惰性求值如何实现?

Here are a four different lists, where the first three are already evaluated.

The first one, l, was defined as a top level constant as

> l = [1,2,3]

and is now found at 0xaf305d90 (where the /2 is the pointer tag information) and fully evaluated:

> ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1}, ptrArgs = [0xb2efaff4,0xaf2d4248], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = ":"}

The second one, l2, is locally defined

> let l2 = 4:l

and now found at 0xaf305870. See how the cons-cell references l!

> ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1}, ptrArgs = [0xb2efb00c,0xaf305d90], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = ":"}

And the binding

> args

gives us at 0xb2f6920c/1 a static, but at compile time unknown list:

> ConsClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = CONSTR_NOCAF_STATIC, srtlen = 0}, ptrArgs = [], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = "[]"}

And now we have, at 0xaf305858, the concatenation of them, but unevaluated:

> let x = l ++ l2 ++ args

The thunk keeps a reference to l2 and args, but not l, as that is at a static address, unless you are running this in GHCi:

> APClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = AP, srtlen = 0}, arity = 21669, n_args = 2, fun = 0xaf305d74, payload = [0xaf305870,0xb2f6920c/1]}

Now to some more closure types. m and m' locally bound of type the unboxed type Int#, with values 42 resp. 23.

> let f = \x n -> take (I# m + I# x) n ++ args

> t = f m' l2

So here is (0xafd3be14), referencing its free variables args and 42:

> APClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = AP, srtlen = 0}, arity = 57205, n_args = 2, fun = 0xaeff8360, payload = [0xb2f6920c/1]}

And t is a thunk that applies f (also referenced here) to an unboxed value (23) and l2:

> APClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = AP, srtlen = 0}, arity = 58149, n_args = 3, fun = 0xaeff837c, payload = [0xafd3be14,0xaf305870]}

Lastly, here is the standard example for self reference:

> let x = id (:) () x

This is what x (0xb05d0108) looks like, at least without -O:

> APClosure {info = StgInfoTable {ptrs = 0, nptrs = 0, tipe = AP, srtlen = 0}, arity = 216, n_args = 1, fun = 0xaeff7084, payload = [0xb05d0108]}

So it is unevaluated. Let us evaluate it using seq. Now we have, still at 0xb05d0108:

> BlackholeClosure {info = StgInfoTable {ptrs = 1, nptrs = 0, tipe = BLACKHOLE, srtlen = 0}, indirectee = 0xb0417d20/2}

The thunk was replaced by an indirection. If we look at the target, 0xb0417d20/2, we see that it is a newly created cons-cell referencing the original location of x:

> ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1}, ptrArgs = [0xb2f690f4,0xb05d0108], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = ":"}

After running the garbage collector (performGC), we find that the address of x is now 0xb0056094/2 and that the self-reference is without indirections:

> ConsClosure {info = StgInfoTable {ptrs = 2, nptrs = 0, tipe = CONSTR_2_0, srtlen = 1}, ptrArgs = [0xb2f690f4,0xb0056094/2], dataArgs = [], pkg = "ghc-prim", modl = "GHC.Types", name = ":"}