List Concatenation of Different Types


I was trying to build a dynamic list of actors to ignore for a line trace:

!result? : SystemLib.line_trace_single_for_objects(
    {EObjectTypeQuery.@@object_type_world_static, EObjectTypeQuery.@@object_type_vehicle}
    actors_to_ignore : BP_LapProgress.instances + BP_RacingPowerup.instances)

I thought that BP_LapProgress.instances + BP_RacingPowerup.instances should compile but it doesn’t. Now I notice that:

{1 2 "three"} + {"four" "five" "six"} // compiles
{1 2 3} + {"four" "five" "six"} // doesn't compile

So maybe this is also by design where only lists of the same type are meant to be added together.

My work-around right now:

!l : {}

List manipulation enhancements

This is by design. Only lists of compatible types can be added together.

!nums: {1 2 3}
!strs: {"one" "two" "three"}
!numstrs: nums + strs  // Integer and String are not compatible

If you don’t care about the list item type you can use Object as an item type and do the following:

!nums: {1 2 3}
!strs: {"one" "two" "three"}

// Make an empty list and append to it
// Brackets needed to ensure correct order
!numstrs1: [{} += nums] += strs
// Basically the same using method instead of operator
!numstrs2: {}.append_list(nums).append_list(strs)
// Start with copy and add to it
!numstrs3: List!copy(nums).append_list(strs)

If you do care about the type you can use a union type which is more specific.
In this case <Integer|String> and in your case it could be Actor.

!nums: {1 2 3}
!strs: {"one" "two" "three"}

// Make an empty list and append to it
// Brackets needed to ensure correct order
// You could use just + though += adds onto the existing list
!numstrs1: [List{<Integer|String>}! += nums] += strs
// Basically the same using method instead of operator
!numstrs2: List{<Integer|String>}!.append_list(nums).append_list(strs)
// Start with copy and add to it
!numstrs3: List{<Integer|String>}!copy(nums).append_list(strs)

We could also add a concatenation constructor that would look like this:

!nums: {1 2 3}
!strs: {"one" "two" "three"}

// Untyped (Ojbect)
!numstrs1: List!join(nums strs)
// Typed (Ojbect)
!numstrs2: List{<Integer|String>}!join(nums strs)

Just let us know if you want us to add this or see if you can make your own.

Calling appending() should just add a list as an item rather than adding each item individually. You probably want to use append_list() instead.

So for your case, you might want to use:

[Actor{} += BP_LapProgress.instances] += BP_RacingPowerup.instances
// or
// or starting with copy
List{Actor}!copy(BP_LapProgress.instances) += BP_RacingPowerup.instances
// or if List!join() were available
List{Actor}!join(BP_LapProgress.instances BP_RacingPowerup.instances)

Typed lists can be tricky. Take a look at the List doc page for examples.

Let me know if this helps.


Thanks this helps. I see now that my previous work-around was creating a list of objects rather than a list of actors.


Going for the shortest version - good choice. :madsci:

The brackets are a bit annoying, though without them the parser sees this:

Actor{} += BP_LapProgress.instances += BP_RacingPowerup.instances

as this:

Actor{} += [BP_LapProgress.instances += BP_RacingPowerup.instances]

And they would be incompatible List item types.


p.s. There are some future parser enhancements for List that would be nice in this situation.


To get around the brackets we could easily make a List@join() method that would keep the same list type and allow several lists to be appended at once.

So instead of this:

[Actor{} += BP_LapProgress.instances] += BP_RacingPowerup.instances

you would use:

Actor{}.join(BP_LapProgress.instances BP_RacingPowerup.instances)

Instead of join() the method name could alternatively be append_lists() or something similar.

Thinking about it more, If adding all instances of a class is super common we could even do this

// Make a list of Actors with instances from the specified classes
// Type would be List{Actor}
Actor.instances_of(BP_LapProgress BP_RacingPowerup)

Feel free to recommend a better name than instances_of(): list_of(), all_of(), list().

What do you think?


I like this!

This looks very pleasing. I think I’d prefer list_of() or maybe list_from() or instances_from().


Okay great.

I’ll add them.

Until then, you could either use the [] += mechanism or make the above methods yourself - it should be pretty easy at least in script form.


I ended up calling the first fuse() to keep it short and taking into consideration list libraries in other languages.

Actor{}.fuse(BP_LapProgress.instances BP_RacingPowerup.instances)

It’s method looks like this:

// instance method List@fuse()
({ThisClass_} lists) ThisClass_

I ended up calling the second instances_from() so that it is grouped with the other instance methods.

Actor.instances_from(BP_LapProgress BP_RacingPowerup)

It’s method looks like this:

// class method Actor@instances_from()
({<ThisClass_>} classes) List{ThisClass_}
  !list: ThisClass_{}[list.append_list(item.instances)]

Pretty simple really for fairly sophisticated routines. :madsci:

They’ll be in the next update.