# Through does not have hold attribute?

Possibly Related to Unexpected behavior of KeyTake.

Consider the following example, where I input #11 (last) is the misbehaving one. Am I missing something or do you agree there is a bug?

In[1]:= assoc = <|1 -> "x", 2 -> "y"|>

Out[1]= <|1 -> "x", 2 -> "y"|>

In[2]:= KeyTake[{1}][assoc]

Out[2]= <|1 -> "x"|>

In[3]:= <|2 -> #[2]|> &[assoc]

Out[3]= <|2 -> "y"|>

In[4]:= f1 = KeyTake[{1}];

In[5]:= f2 = <|2 -> #[2]|> &;

In[6]:= f3[x_] := KeyTake[x, {1}];

In[7]:= f4[x_] := KeyTake[{1}][x];

In[8]:= Join[f1[assoc], f2[assoc]]

Out[8]= <|1 -> "x", 2 -> "y"|>

In[9]:= Through[Join[f4, f2][assoc]]

Out[9]= <|1 -> "x", 2 -> "y"|>

In[10]:= Through[Join[f3, f2][assoc]]

Out[10]= <|1 -> "x", 2 -> "y"|>

In[11]:= Through[Join[f1, f2][assoc]]

During evaluation of In[11]:= Join::heads: Heads KeyTake and Function at positions 1 and 2 are expected to be the same.

Out[11]= <|1 -> "x", 2 -> "y"|>


Inexplicably we still get the correct result. Why is that?

I think the error is caused by the fact that Through Does not have Hold* Attribute, which I find to be strange given what it is supposed to do.

In[12]:= Attributes[Through]

Out[12]= {Protected}


An alternative implementation that does hold arguments seems to work fine, though I haven't tested it too much and it may have other bugs:

ClearAll[through]
SetAttributes[through, HoldAll]
$$$$

Come to think about it, it is simple enough to pass arguments Unevaluated to Through`, so perhaps everything works correctly.