I initially thought that generator/generator expression is cool(sort of
like the lazy evaluation in Haskell) until I notice this side effect.
>>>a=(x for x in range(2))
>>>list(a)
[1,2]
>>>list(a)
[]
Would this make generator/generator expression's usage pretty limited ?
As when the program/system goes beyond a single module, this behaviour
can cause subtle bugs ?
> I initially thought that generator/generator expression is cool (sort of
> like the lazy evaluation in Haskell) until I notice this side effect.
>
> >>>a=(x for x in range(2))
> >>>list(a)
> [1,2]
> >>>list(a)
> []
>
> Would this make generator/generator expression's usage pretty limited ?
nope.
> As when the program/system goes beyond a single module, this behaviour
> can cause subtle bugs ?
sure, in the same way as
>>> f = open(filename)
>>> f.read()
'hello world\n'
>>> f.read() # oops!
''
causes subtle bugs (that is, almost never)
</F>
Now that I notice that, Of course I can be sure I would be careful. But
what about the following situation :
I import some function from some third party module which said, "oh, my
function returns a iteratable". Then I can only list(o) if I want to
pass it around or I consume it in only one and only one place. turning
it into a list completely negate what generator is intended
for(generate as much as you need) and using it in only one and only one
place(like your fread example) would IMO means its usage is pretty
limited.
Beside, I can do a fseek to rewind a file handle but not a generator
object.
Its a question of protocol. A iterator only guarantes that you can fetch
items from it until it is possibly exhausted. In the same way, a stream
may only guarantee you that you can read from it. If you need more, you
have tgo use a different protocol. Lists are one that allows you to
randomly access it. Files allow to seek, in addition to stream semantics.
And given that python is an imperative language with side-effects, you
don't know what sideeffects a generator can cause - which makes a
"rewind" or copy-semantics to make it work several time impossible (in
the general case, that is). So it has to focus on what it _can_ guarantee.
Haskell and other FP languages canwork differently here, as sideeffects
are made excplicit using e.g. monads or other means - which allows for
re-use of a generator-like construct. But there is no way to make this
work in pythons paradigm.
Diez
> Files allow to seek, in addition to stream semantics.
Some files. Not all files support seek operations. Some only support
forward seek.
</F>
I would only use generator as IO monad in Haskell, i.e. don't use it
unless I absolutely need to.
> bon...@gmail.com wrote:
>
>> I initially thought that generator/generator expression is cool (sort of
>> like the lazy evaluation in Haskell) until I notice this side effect.
>>
>> >>>a=(x for x in range(2))
>> >>>list(a)
>> [1,2]
>> >>>list(a)
>> []
>>
>> Would this make generator/generator expression's usage pretty limited ?
>
> nope.
In fairness, it is a pretty big Gotcha.
>> As when the program/system goes beyond a single module, this behaviour
>> can cause subtle bugs ?
>
> sure, in the same way as
>
> >>> f = open(filename)
> >>> f.read()
> 'hello world\n'
> >>> f.read() # oops!
> ''
>
> causes subtle bugs (that is, almost never)
Are you saying that the bugs it causes aren't subtle? *wink*
--
Steven
Exactly. Destructive generator problems are caught almost immediately.