I'm quite used to it now, so I'm struggling to remember what about it got me, 
but initially I always found myself referring to the actual implementation 
every time I came across that syntax, so it wasn't at all fluid---I therefore 
must have been conceptualizing it incorrectly. Note I hadn't ever used Ruby 
before.

I think a variant of Peter's original point is the best one: in
    map(collection) do x
and
    open("outfile", "w") do f
what x and f are is not entirely obvious. Some elaboration:

First, neither x nor f is something "to be done", so "do f" is semantically a 
little strange. "do_to f" might be semantically clearer, but I'm not lobbying 
to change it (I'm just trying to work through in my own head what makes it 
confusing).

Second, in the latter example, f can erroneously be thought of as meaning the 
output of open("outfile", "w") rather than the input to the anonymous function. 
So there's a potential cognitive gotcha: you start thinking of this as some 
weird outputs-are-declared-on-the-RHS construct. The fact that `cd` doesn't 
return anything---coincidentally reinforcing that view---doesn't help the 
matter. The map example shows that this view is broken, but somehow my eyes 
were always attracted to the section on cd/open, and I think that was 
counterproductive.

Third, even once you re-read and grok the part that says that the symbols 
after the "do" are inputs to the anonymous function, it's not immediately 
clear how they are initialized. One might think there's some overall rule of 
the language, but instead it's specific to the implementation of the "outer" 
function. Of course, now that I grok it I can usually guess how they are 
initialized ("how would I design it?" proves to be a pretty reliable rule).

I just pushed another attempt to further clarify these points in the manual. 
Most importantly/controversially, I deleted mention of cd(), because I worry 
that joining open and cd together is kind of rushing things for people for 
whom this may be unfamiliar. Stefan, feel free to hack away at this as you 
please---if you like your old versions better, well, you are a git master! :)

--Tim


On Monday, April 28, 2014 11:47:12 AM 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.
> 
> 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