Recursive GetChildren

Instead of writing your own function for it every single time, what if we had recursive functionality with Instance:GetChildren() ?

This would be extremely useful and FindFirstChild supports recursion, so why not?

Possible examples:

Instance:GetChildren(bool recursive = false) Instance:GetChildrenRecursive()
Or as Echo suggested:

Instance:GetDescendants()

This would be great, just like Instance:findFirstChild(string, recursive = false). That way if you do specify you want it to be recursive, all you have to do is type in Instance:GetChildren(true). No need for a new function. :slight_smile:

This seems too easy for the need of it being a parameter.

I have talked with zeuxcg about this. Roughly speaking, he thinks that making a gigantic table of an instances’ descendants is inefficient and unnecessary because it can already be accomplished with a recursive function, and that if it were to implemented, it would be done as an iterator for efficiency.

I think the concept of iterators is confusing to most developers, and would negate any benefits. You can roll your own iterator though, it’s very easy.

[quote] I have talked with zeuxcg about this. Roughly speaking, he thinks that making a gigantic table of an instances’ descendants is inefficient and unnecessary because it can already be accomplished with a recursive function, and that if it were to implemented, it would be done as an iterator for efficiency.

I think the concept of iterators is confusing to most developers, and would negate any benefits. You can roll your own iterator though, it’s very easy. [/quote]

I agree. Recursion is more readable and allows for better handling.

I’ve never come across a situation where I’ve needed to do this, which makes me curious. What are you doing so much that would warrant a change in the API?

@Jo: I’d have to disagree. If this were something to be added to the API, the best way off adding it would be through Instance:GetDescendants ()

Would iterators be confusing though? You’d just use it as follows

for p in i:GetDescendants() do ... end

(we’d probably pick a better name though)

Back when we were talking about this we did not have an easy way to implement this but I had to make some changes to our reflection internals for smooth terrain and it actually seems to be easy to do now.

P. S.
I have a snippet that I use really frequently which makes me think that having GetDescendants is not a bad idea…

  function R(p, f) f(p) for _, c in pairs(p:GetChildren()) do R(c, f) end end R(workspace, function (p) ... end)

[quote] Would iterators be confusing though? You’d just use it as follows

for p in i:GetDescendants() do ... end

(we’d probably pick a better name though)

[/quote]

What’s wrong with the name? It follows the same naming convention as :GetChildren() – :GetChildren gets the children of the model, the direct descendants, while :GetDescendants() would get all of the descendants of the model. Not only does it use the same naming convention as GetChildren, but it does exactly what it says it does.

I don’t think iterators would be confusing either – it’d be just the same as looping through the children.

local mass = 0
for descendant in character:GetDescendants() do
    if descendant:IsA("BasePart") then
        mass = mass + descendant:GetMass()
    end
end

compared to:

local numChildren = 0
for child in character:GetChildren() do
    numChildren = numChildren + 1
end

I would be fine with

for object in workspace:IterateDescendants() do
    print(object.Name)
end

The problem is that scripters will write lots of code like this:

for object in pairs(workspace:IterateDescendants()) do
end

for _, object in workspace:IterateDescendants() do

end

But maybe it’s still worth implementing.

One question: if IterateDescendants/GetDescendants were implemented, how would it work?

Would it do something like this, in order?

 -  Parent
 |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child
 |   |   -  Child

[quote] The problem is that scripters will write lots of code like this:

[code]
for object in pairs(workspace:IterateDescendants()) do
end

for _, object in workspace:IterateDescendants() do

end
[/code] [/quote]

Other than people iterating through thousands of instances when they shouldn’t have to, what’s wrong with a loop like that?

[quote]
Other than people iterating through thousands of instances when they shouldn’t have to, what’s wrong with a loop like that? [/quote]

If they are iterating through something that big it’s their own fault :confused:
Besides it wouldn’t be bad unless you’re doing it often.
I, for example would only use it once every time a new map is loaded

[quote] I would be fine with

for object in workspace:IterateDescendants() do
    print(object.Name)
end

The problem is that scripters will write lots of code like this:

for object in pairs(workspace:IterateDescendants()) do
end

for _, object in workspace:IterateDescendants() do

end

But maybe it’s still worth implementing. [/quote]

YOU DONT HAVE TO USE PAIRS OR “_,”?
WHY DIDNT I KNOW THIS.

1 Like