Reputation: 177
I have a list of anonymous functions that I need to map over a list of argument lists. My desire is to obtain a list containing lists whose elements are the functions in the functions list, evaluated at each argument list.
My first thought was to map the functions list over the argument lists and then apply the functions in the functions list on each element in the arguments list.
;; definitions for k functions
let fj [ [x1 x2 ... xn ] -> <body j> ]
...
let args [ [ ... ] [ ... ] ... [ ... ] ] ;; list of arguments
let f-list ( list f1 f2 ... fk )
map [ [ arg ] -> map [ [ f ] -> ( runresult f arg ) f-list ] ] args
There is one two problem with this code:
f-list
on list arg
does not behave the way I expected it to behave. Namely, running the code produces run-time errors because the functions in f-list
are not defined over a list but are instead defined over a number of arguments. In order to overcome this latter difficulty, I have redefined the functions in f-list
so as to receive a list as an argument and use item
in the body of the functions in order to retrieve individual parameters.
This solution, apart from the fact that, it too, feels like a hack, it is also highly impractical because it increases the code needed to obtain a given result, in a way that is highly error prone, not to mention extremely tedious ( consider having to redefine a modest number of functions with a moderate number of arguments ).
In Mathematica it is possible to transform a list of arguments to a function into a sequence ( or tuple ) of arguments by using Apply
as in Apply[f, args]
where args
is a list of argument values.
This facilitates the application of functions on lists of argument ( lists ). Practically, one can write f @@@ { args1, args2, ..., argsm }
and obtain a list { f[x11, x12, ..., x1n], f[x21, x22, ..., x2n], ..., f[xm1, xm2, ..., xmn] }
( where @@@
is just the infix notation that corresponds to Apply[f, args, 1]
).
I guess what I'm looking for is how to achieve the same result in native NetLogo code without having to resort to hacks like the one reported in the former part of this question.
globals [ f-list args ]
to setup
let f1 [ [ arg ] -> ( ( item 0 arg ) - 5 ) ^ 2 + ( ( item 1 arg ) - 5 ) ^ 2 + 0 * ( ( item 2 arg ) - 5 ) ^ 2 ]
let f2 [ [ arg ] -> 4 * ( item 1 arg ) ^ 2 + 4 * ( item 0 arg ) ^ 2 + 0 * ( item 2 arg ) ^ 2 ]
let f3 [ [ arg ] -> 2 + ( ( item 1 arg ) - 2 ) ^ 2 + ( ( item 2 arg ) - 1 ) ^ 2 + 0 * ( item 0 arg ) ]
let f4 [ [ arg ] -> 9 * ( item 0 arg ) - ( ( item 2 arg ) - 1 ) ^ 2 + 0 * ( item 1 arg ) ]
set f-list ( list f1 f2 f3 f4 )
set args [ [ 2.04 3.09 -1.32 ] [ 5.57 -3.9 4.0 ] [ -1.1 -0.432 8.0 ] [ 1.32 -2.3 -9.103 ] ]
show map [ [ arg ] -> ( map [ [ f ] -> ( runresult f arg ) ] f-list ) ] args
end
using a setup
button that calls the procedure above produces the following output:
observer: [[12.4097 54.8388 8.570500000000001 12.977599999999999] [79.53490000000001 184.9396 45.81 41.13] [66.716624 5.586496 56.914624 -58.9] [66.83239999999999 28.129599999999996 122.56060899999999 -90.190609]]
Upvotes: 1
Views: 127
Reputation: 14972
Thanks to Bryan Head, NetLogo now offers this functionality via the (experimental and undocumented) __apply
and __apply-result
primitives.
In your case, __apply-result
is the one you need:
globals [ f-list args ]
to setup
let f1 [ [x y z] -> (x - 5) ^ 2 + (y - 5) ^ 2 + 0 * (z - 5) ^ 2 ]
let f2 [ [x y z] -> 4 * y ^ 2 + 4 * x ^ 2 + 0 * z ^ 2 ]
let f3 [ [x y z] -> 2 + (y - 2) ^ 2 + (x - 1) ^ 2 + 0 * x ]
let f4 [ [x y z] -> 9 * x - (z - 1) ^ 2 + 0 * y ]
set f-list (list f1 f2 f3 f4)
set args [[2.04 3.09 -1.32] [5.57 -3.9 4.0] [-1.1 -0.432 8.0] [1.32 -2.3 -9.103]]
print map [ arg -> map [ f -> __apply-result f arg ] f-list ] args
end
As you can see, __apply-result
takes two arguments, an anonymous reporter and a list, and automatically passes the items in the list as arguments to the anonymous reporter. The __apply
primitive is similar, but takes an anonymous command instead of an anonymous reporter.
Upvotes: 2