# Defining an operator: Partially evaluate a Pure Function

I would like to define an operator that takes some parameters as input and returns a function. Here is an example:

operator[indexLists_] := Function[weights,Table[Total[weights[[indexLists[[i]]]]], {i, Length[indexLists]}]];
example = {{1, 2, 3}, {5, 2, 1}, {1, 2}, {6, 7}};
op1 = operator[example]


which returns

Function[weights$, Table[Total[ weights$[[{{1, 2, 3}, {5, 2, 1}, {1, 2}, {6, 7}}[[i]]]]], {i, Length[{{1, 2, 3}, {5, 2, 1}, {1, 2}, {6, 7}}]}]]


what I would want is a partially evaluated version, i.e.

op2 = Function[weights, {Total[weights[[{1, 2, 3}]]], Total[weights[[{5, 2, 1}]]], Total[weights[[{1, 2}]]], Total[weights[[{6, 7}]]]}]


Both op1 and op2 return functions that perform the same thing, e.g. when called with "Range" as argument they return {6, 8, 3, 13}.

This is a toy example. In my real example, the function returned by the operator performs some complex transformation of the input parameter "weights" that I want to pre-compute in order to be more efficient when evaluating the function many times. I could not figure out how to get around to HoldAll attribute of the pure function.

One idea is to use Inactive/Activate:

operator[indexLists_] := Block[{weights},
Activate @ Inactive[Function][
weights,
Table[Inactive[Total][Inactive[Part][weights,indexLists[[i]]]],{i,Length[indexLists]}]
]
]


Inactivating Function wasn't strictly necessary, but it prevented the variable weights from being modularized to weights\$. Inactivating Total and one of the Part functions prevented undesired evaluations. Your example:

example = {{1,2,3},{5,2,1},{1,2},{6,7}};
op1 = operator[example]


Function[weights, {Total[weights[[{1, 2, 3}]]], Total[weights[[{5, 2, 1}]]], Total[weights[[{1, 2}]]], Total[weights[[{6, 7}]]]}]

and

op1[Range]


{6, 8, 3, 13}

An approach to circumvent the HoldAll attribute is to "inject" the expressions into Function after (partially) evaluating them:

operator[indexLists_] :=
Block[{weights, f},
Function[weights, #] & @Thread[f[weights, indexLists]] /.
f[xx__] :> Total[Part[xx]]]


Inside Block, I clear not only the variable weights but also an auxiliary f that is replaced at the very end with Total[Part[...]]. This replacement rule is one way to inject things into held expressions. Before that, I first create a slot # inside Function into which I insert the evaluated Table generated by the indexList argument to operator. This is where the temporary name f is used as a placeholder for the desired operation which can't be executed at that stage. It creates the necessary structure inside Function into which the replacement rule then inserts Total[Part[...]].
{"ft_lang_label":"__label__en","ft_lang_prob":0.83024246,"math_prob":0.988,"size":1117,"snap":"2021-31-2021-39","text_gpt3_token_len":361,"char_repetition_ratio":0.15274034,"word_repetition_ratio":0.072289154,"special_character_ratio":0.36078784,"punctuation_ratio":0.24313726,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.984592,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-07-27T22:50:05Z\",\"WARC-Record-ID\":\"<urn:uuid:15c7ca1d-1695-48af-a86c-c5045bec9117>\",\"Content-Length\":\"176680\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:6751b2b7-e444-4bc7-9723-fe20d58c1c14>\",\"WARC-Concurrent-To\":\"<urn:uuid:8c729ebf-3d82-417f-9269-e69b8ae6c1a2>\",\"WARC-IP-Address\":\"151.101.1.69\",\"WARC-Target-URI\":\"https://mathematica.stackexchange.com/questions/151011/defining-an-operator-partially-evaluate-a-pure-function\",\"WARC-Payload-Digest\":\"sha1:KUMV6BEQRCRHJXJWFIUB7O226Y453T4J\",\"WARC-Block-Digest\":\"sha1:HQB7IBMS6RCMUJIWKIGKGCCQNY6AJCBE\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-31/CC-MAIN-2021-31_segments_1627046153491.18_warc_CC-MAIN-20210727202227-20210727232227-00347.warc.gz\"}"}