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:

SetAttributes[through, HoldAll]
through[head_[args__][arg__]] := Apply[head, Map[#[arg] &, {args}]];

In[31]:= through[Join[f1, f2][assoc]]

Out[31]= <|1 -> "x", 2 -> "y"|>
  • $\begingroup$ I'd say it's expected, but yeah: it's sometimes a bit of an inconvenience that Through and Thread do not hold their arguments. $\endgroup$ Aug 19, 2021 at 8:21

1 Answer 1


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


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.