JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.64k stars 5.48k forks source link

Allow combining getindex and do syntax #31106

Open bicycle1885 opened 5 years ago

bicycle1885 commented 5 years ago

Currently, combining the getindex and the do syntax in the following way is not allowed:

julia> :(file[path] do x; end)
ERROR: syntax: missing comma or ) in argument list

julia> :(open(path) do x; end)  # Of course, this is fine.
:(open(path) do x
      #= REPL[8]:1 =#
  end)

Any reason not to allow this?

I think this syntax is sometimes useful. For example, you're writing a binding package to a C library (say HDF5) and you start to think file[path] is nice syntax to get some object by allocating some resources. But the object should be deallocated as soon as it gets unreachable, and so you want to use the do block syntax in the same way as the open function.

StefanKarpinski commented 5 years ago

The syntax could certainly be allowed but

file[path] do x
    code
end

would seem to mean

getindex(file, path) do x
    code
end

which lowers to

getindex(x -> code, file, path)

which is the wrong signature for calling getindex.

vtjnash commented 5 years ago

We don't necessarily need to lower it the same, but I do have a similar question of what should happen to that thunk. I almost feel like this looks like syntax for an in-place update, lowering to:

file[path] = (x -> code)(file[path])

e.g. that

file[path] do x; x + 1; end

is the same as

file[path] += 1

Although I don't have any particular argument for why this would be especially useful.

(aside: the rough current equivalent with do and functions might be like replace!(Ref(file, path)) do x; x + 1; end—but we don't really currently have a functional representation of the in-place update syntax)

bicycle1885 commented 5 years ago

I'm not perfectly sure why getindex(x -> code, file, path) is the wrong signature. Because overloading the getindex syntax of an anonymous function? I think it is not necessary to lower it to getindex as @vtjnash says.

I'd like to use this syntax to achieve the open-manipulate-close pattern, and therefore I think lowering it to some_func(thunk, file, path) is good. some_func may be getindex or any other function.

mbauman commented 5 years ago

I'm not perfectly sure why getindex(x -> code, file, path) is the wrong signature.

The key is that getindex(x -> code, file, path) is equivalent to (x -> code)[file, path]. I'd rather see it be file[x->code, path] because the entire dispatch table of getindex is predicated on specializing the first argument. Spelling it like file[x->code, path] encapsulates the special behavior completely upon your custom file type. Spelling it like (x -> code)[file, path] feels a little less contained — you're defining a form of indexing for all functions! But I agree the lowering argument is a little moot... in fact we've discussed a very similar hypothetical lowering for A.[x]!