Arcensoth / imp-spec

IMP: Interoperable Module Protocol design specification and recommendations for Minecraft datapacks.
18 stars 1 forks source link

@within should explicitly allow @private access #2

Open NeunEinser opened 3 years ago

NeunEinser commented 3 years ago

From the current specification, it is unclear whether a function with a @within visibility is allowed to call itself.

However, it happens commonly for me, that I need a loop that is tailored to be used in a specific function and should not be used elsewhere. Dph+ follows the specification in that regard and errors when I try to call a @within-defined function from within itself so I commonly end up with things like these:

#> 91:loop
# ...
# @within
#   function 91:parent
#   function 91:loop

I would like to avoid this and generally think it is weird to be able to make a function invisible for itself.

Arcensoth commented 3 years ago

I think a case could be argued either way, but I can't say for certain whether I considered this case at all when writing the documentation. I'll have to take a deeper look.

IIRC DHP also allows globs, so you can do something like @within namespace:some/folder/* as well. Not sure if that makes a difference here, but I thought it was worth mentioning.

NeunEinser commented 3 years ago

I think a case could be argued either way

What would be an argument against it?

IIRC DHP also allows globs, so you can do something like @within namespace:some/folder/* as well. Not sure if that makes a difference here, but I thought it was worth mentioning.

That's true, but there may be other files in that folder which have no business for the within function

Arcensoth commented 3 years ago

What would be an argument against it?

Playing devil's advocate here: with multiple similarly-named functions you could accidentally introduce an infinite loop and it would be difficult to track down. If functions are by default hidden from themselves, this is unlikely to happen unless you've explicitly stated that the function can run itself. That being said, it's still possible to introduce a larger, external circular reference.

The driving purpose of @within is to be explicit, so instead of sacrificing this explicitness I'm thinking of instead introducing a separate annotation like @recursive for the cases where a function calls itself directly. So basically @recursive would imply @within <self> and would mean you don't get a warning when the function calls itself directly.

Another, similar idea: introduce @recursive which works identical to @within except it also implicitly allows itself. I think this could be a nice way to distinguish between parent-child relationships vs looping.

NeunEinser commented 3 years ago

I think in general, I'd like an annotation like @loop more, as in most cases, while it's implemented as a recursion because of mcfunction's limitations, it actually is a loop.

Perhaps this could even be taken further, with an annotation @foreach <element-description> in <list-description> and @while <condition-description> additionally to @recursive. These would also allow you to declare more information about the function. @foreach may also be used like this: @foreach i in 1..input_param to declare a classical for-loop.

Should this imply that a function that is not tagged with any of these implies it cannot call itself, no matter the access level?

Another, similar idea: introduce @recursive which works identical to @within except it also implicitly allows itself. I think this could be a nice way to distinguish between parent-child relationships vs looping.

In that case, I think the name recursive is misleading. @recursive <function-name> appears as if the mentioned function is recursive and not the function where it is declared. I generally don't like this idea too much.