How do I use array callables as callables?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Vadalken

I want to filter an array by the elements of another array. I would like to do this by using the two array methods filter() and has(). Ideally this would be as simple:

var list_1 = [1,2,3]
var list_2 = [2,4]
var list_3 = list_1.filter(list_2.has)     # list_3 is now [2]

This does however not work, throwing an error telling me arrays do not have the parameter “has”. Ok here is try number 2.

var list_3 = list_1.filter( Callable(list_2, "has") )

This does not work since an array is not a GDscript Object and therefore the Callable constructor throws an error in the editor.

Is there a way to make this work without needing to make an extra function and calling it instead?

func _ready():
	var list_3 = list_1.filter(filter_2)

func filter_2(thing):
	return list2.has(thing)

This works, but I lose the ability to easily change what array i am filtering by.

I have tried a lot of different things to make this work, but the same two problems always stop me:

object.function_name # Always treated as a parameter.
array.get("function_name") # Error since an array is not a GDscript Object.

has a method that returns a bool

var list_1 = [1,2,3]

list_1.has(3) # is true

honeycoffee | 2023-06-30 15:14

Yes I know. filter() takes a method returning a bool as an argument.

Vadalken | 2023-06-30 15:17

I edited it so the noted list_3 output is theoretically correct. But the output is not the issue. There is no output since it will not run at all.

Vadalken | 2023-06-30 15:20

You are not using has() as a method, that’s why it’s not running ^^;;;;

Write a function like this:

func intersectionArray(list1, list2):
newList = new Array
foreach item in list1:
if list2.has(item)

return newList

Maybe there is a more elegant solution but this will work

honeycoffee | 2023-06-30 15:31

:bust_in_silhouette: Reply From: jgodfrey

Something like this should work I think…

var list_1 = [1,2,3]
var list_2 = [2,4]
var list_3: Array
list_3.assign(list_1.filter(func(n): return list_2.has(n))) 

Or, slightly cleaner…

var list_1 = [1,2,3]
var list_2 = [2,4]
var list_3: Array = list_1.filter(func(n): return list_2.has(n))

jgodfrey | 2023-06-30 16:04

Was not familiar enough with lambda functions to consider this. Thank you.

Vadalken | 2023-06-30 23:23