* open(...) do ... end * comes from Ruby, but I agree it can be confusing
if you're not already familiar with the construct.
On Monday, April 28, 2014 6:06:37 PM UTC+2, Simon Byrne 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
>>>
>>
>>