0

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]
through[head_[args__][arg__]] := Apply[head, Map[#[arg] &, {args}]];

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

Out[31]= <|1 -> "x", 2 -> "y"|>
```
Michael E2
  • 235,386
  • 17
  • 334
  • 747
Shwouchk
  • 497
  • 3
  • 8
  • 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. – Sjoerd Smit Aug 19 '21 at 08:21

1 Answers1

1

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

Shwouchk
  • 497
  • 3
  • 8