Ok, I did some poking around old PEPs and although the reasoning for not
using closures isn't in PEP
343<http://legacy.python.org/dev/peps/pep-0343/>(with/as), it is in
PEP
340 <http://legacy.python.org/dev/peps/pep-0340/> if you search down to
"Comparison to Thunks". The basic issue that Guido has with something like
a do block is that return inside the block returns from the block, not the
enclosing function. That's a fair point and I raised that issue myself at
some point, but we decided to just live with it. Ruby addresses the same
issue by giving blocks different behavior from closures, which is kind of
awful.


On Mon, Apr 28, 2014 at 12:23 PM, Stefan Karpinski <[email protected]>wrote:

> Did Python just choose `with` instead of blocks because its closures were
> (at the time) too broken to make the block approach work well and with can
> be implemented without working closures?
>
>
> On Mon, Apr 28, 2014 at 12:20 PM, Stefan Karpinski 
> <[email protected]>wrote:
>
>> Python has the with 
>> keyword<https://docs.python.org/release/2.5/whatsnew/pep-343.html>,
>> which serves a similar role. However, I have to admit that I've never
>> really understood how the Python style `with` approach is a better than the
>> Ruby-style (do)-blocks. The with keyword seems more limiting since you
>> can't, for example, evaluate the block multiple times. Does anyone have any
>> reasons why the with approach is better?
>>
>>
>> On Mon, Apr 28, 2014 at 12:06 PM, Simon Byrne <[email protected]>wrote:
>>
>>> On Monday, 28 April 2014 16:47:12 UTC+1, Stefan Karpinski wrote:
>>>>
>>>> It's odd to me that this is an issue because this is possibly the least
>>>> deep feature of the language – it's literally just a way to put parentheses
>>>> in less awkward places. But if Ruby's do blocks have any lesson to teach,
>>>> it's that this relatively small syntax change can make higher order
>>>> programming appealing and common, rather than niche.
>>>>
>>>
>>> My own perspective is that this is due to two reasons
>>>
>>> 1) `do` is the only (non-macro) construction that rewrites expressions
>>> i.e.
>>>
>>> open("outfile", "w") do f
>>>   write(f, data)
>>> end
>>>
>>> does not (directly at least) call the method `open("outfile", "w")`
>>>
>>> 2) In the case of `open` in particular, it is an exception to the
>>> general duck typing behaviour that methods should have broadly consistent
>>> behaviour with different arguments. Perhaps this would be less confusing if
>>> it was called `withfile` or something similar?
>>>
>>>
>>>
>>>
>>>>
>>>> On Mon, Apr 28, 2014 at 6:43 AM, Tim Holy <[email protected]> wrote:
>>>>
>>>>> The "do" block syntax was for me one of the more difficult aspects of
>>>>> Julia's
>>>>> syntax to wrap my head around, although now I use it frequently. I just
>>>>> expanded this section of the manual, trying to incorporate elements of
>>>>> this
>>>>> discussion.
>>>>>
>>>>> --Tim
>>>>>
>>>>> On Monday, April 28, 2014 12:57:23 AM Peter Simon wrote:
>>>>> > Going back and rereading the 'open' documentation,  it clearly
>>>>> states that
>>>>> > the method taking a function as its first argument will apply that
>>>>> function
>>>>> > to the file handle returned by the method without the handle.
>>>>> Thanks for
>>>>> > your patience.
>>>>> >
>>>>> > On Apr 27, 2014 9:41 PM, "Peter Simon" <[email protected]> wrote:
>>>>> > > Ah, you just switched on the light for me.  I thought that the
>>>>> example was
>>>>> > > illustrating a general principle, but in fact the essential feature
>>>>> > > depends
>>>>> > > on knowledge of the way that the 'open' method is coded.
>>>>> > >
>>>>> > > Thanks!
>>>>> > >
>>>>> > > On Apr 27, 2014 9:24 PM, "Amit Murthy" <[email protected]> wrote:
>>>>> > >> The actual function as defined in base/io.jl
>>>>> > >>
>>>>> > >> function open(f::Function, args...)
>>>>> > >>
>>>>> > >>     io = open(args...)
>>>>> > >>     try
>>>>> > >>
>>>>> > >>         f(io)
>>>>> > >>
>>>>> > >>     finally
>>>>> > >>
>>>>> > >>         close(io)
>>>>> > >>
>>>>> > >>     end
>>>>> > >>
>>>>> > >> end
>>>>> > >>
>>>>> > >> Just multiple dispatch at work. The 'open' variant without a file
>>>>> handle
>>>>> > >> is called first.
>>>>> > >>
>>>>> > >> On Mon, Apr 28, 2014 at 9:44 AM, Peter Simon <[email protected]
>>>>> >wrote:
>>>>>
>>>>> > >>> Right, I don't have a problem with that.  I simply used "inner"
>>>>> as a way
>>>>> > >>> to refer to the function that is used as the first argument to
>>>>> the other
>>>>> > >>> ("outer") function.  Sorry if I abused a conventional meaning of
>>>>> these
>>>>> > >>> terms.
>>>>> > >>>
>>>>> > >>> I would like to know how this anonymous function (in the "open"
>>>>> example)
>>>>> > >>> is passed the file handle.  My confusion stems from the fact
>>>>> that this
>>>>> > >>> handle, to my knowledge, is not available until the "open"
>>>>> function
>>>>> > >>> provides it as its return value.
>>>>> > >>>
>>>>> > >>> On Sunday, April 27, 2014 8:59:50 PM UTC-7, Amit Murthy wrote:
>>>>> > >>>> It is just a way to define an anonymous function. It is not a
>>>>> way to
>>>>> > >>>> define an "inner" function in that sense.
>>>>> > >>>>
>>>>> > >>>> On Mon, Apr 28, 2014 at 9:24 AM, Peter Simon <
>>>>> [email protected]>wrote:
>>>>> > >>>>> My question concerns where this handle comes from.  Isn't the
>>>>> handle
>>>>> > >>>>> coming from the output of 'open'?  Since 'open' is the "outer"
>>>>> > >>>>> function of
>>>>> > >>>>> the 'do' construct, then why doesn't the outer function in the
>>>>> first
>>>>> > >>>>> example also supply its output as input to its inner function?
>>>>> > >>>>>
>>>>> > >>>>> On Sunday, April 27, 2014 8:40:27 PM UTC-7, Amit Murthy wrote:
>>>>> > >>>>>> Without using a do-block, you would need to pass in a
>>>>> function as the
>>>>> > >>>>>> first argument to 'map'.
>>>>> > >>>>>> 'open' has a variant where the first argument is again a
>>>>> function
>>>>> > >>>>>> that accepts an open handle.
>>>>> > >>>>>>
>>>>> > >>>>>> The do-block syntax in this case just allows you to define
>>>>> the said
>>>>> > >>>>>> function.
>>>>> > >>>>>>
>>>>> > >>>>>> On Mon, Apr 28, 2014 at 8:55 AM, Peter Simon
>>>>> <[email protected]>wrote:
>>>>> > >>>>>>> In the Julia manual, the second example in
>>>>> > >>>>>>> block-syntax-for-function-arguments<http://docs.
>>>>> julialang.org/en/lat
>>>>> > >>>>>>> est/manual/functions/#block-syntax-for-function-arguments>
>>>>> contains>>>>>>>
>>>>> > >>>>>>> the following do block:
>>>>> > >>>>>>>     open("outfile", "w") do f
>>>>> > >>>>>>>
>>>>> > >>>>>>>         write(f, data)
>>>>> > >>>>>>>
>>>>> > >>>>>>>     end
>>>>> > >>>>>>>
>>>>> > >>>>>>> and the documentation states that "The function argument to
>>>>> open
>>>>> > >>>>>>> receives a handle to the opened file."  I conclude from this
>>>>> that
>>>>> > >>>>>>> the return value (i.e., the file handle) of the open
>>>>> function is
>>>>> > >>>>>>> passed to this function f -> write(f, data) that is used as
>>>>> the
>>>>> > >>>>>>> first argument of open.  So far, so good (I think).  But now
>>>>> I go
>>>>> > >>>>>>> back and take another look at the first do block example:
>>>>> > >>>>>>>
>>>>> > >>>>>>> map([A, B, C]) do x
>>>>> > >>>>>>>
>>>>> > >>>>>>>     if x < 0 && iseven(x)
>>>>> > >>>>>>>
>>>>> > >>>>>>>         return 0
>>>>> > >>>>>>>
>>>>> > >>>>>>>     elseif x == 0
>>>>> > >>>>>>>
>>>>> > >>>>>>>         return 1
>>>>> > >>>>>>>
>>>>> > >>>>>>>     else
>>>>> > >>>>>>>
>>>>> > >>>>>>>         return x
>>>>> > >>>>>>>
>>>>> > >>>>>>>     endend
>>>>> > >>>>>>>
>>>>> > >>>>>>> I try to interpret this example in light of what I learned
>>>>> from the
>>>>> > >>>>>>> second example.  The map function has a return value,
>>>>> consisting of
>>>>> > >>>>>>> the array [A, B, C], modified by applying the function in
>>>>> the do
>>>>> > >>>>>>> block to each element.  If this example behaved like in the
>>>>> second
>>>>> > >>>>>>> example, then the output of the map function should be
>>>>> passed as an
>>>>> > >>>>>>> input to the function defined in the do block.  Clearly this
>>>>> > >>>>>>> doesn't happen, so the lesson I learned from the second
>>>>> example
>>>>> > >>>>>>> doesn't apply here, apparently.  Why not?  Under what
>>>>> conditions is
>>>>> > >>>>>>> the output of the outer function passed as an input to the
>>>>> inner
>>>>> > >>>>>>> function?
>>>>> > >>>>>>>
>>>>> > >>>>>>> I must be looking at this wrong and would appreciate some
>>>>> help in
>>>>> > >>>>>>> getting my mind right :-).
>>>>> > >>>>>>>
>>>>> > >>>>>>>
>>>>> > >>>>>>> Thanks,
>>>>> > >>>>>>>
>>>>> > >>>>>>> Peter
>>>>>
>>>>
>>>>
>>
>

Reply via email to