1

Consider the following:

Quit[]
Thread[g[{1, 2}, 3]]
(* {g[1, 3], g[2, 3]} *)

Thread[g[{}, 3]]
(* {} *)

This works similarly if instead $g$ takes only one parameter. Now look at the following:

Quit[]
f1[x_] := x+3;
f2[x_,y_] := x + y + {1,0};

Thread[f1[{1,2}]]
(* {4, 5} *)
Thread[f1[{}]]
(* {} *)

Thread[f2[{1,2},5]]
(* {7, 7} *)
Thread[f2[{},5]]
(* Thread::tdlen: Objects of unequal length in {}+5+{1,0} cannot be combined. *)
(* Thread::tdlen: Objects of unequal length in 5+{}+{1,0} cannot be combined. *)
(* 5 + {} + {1, 0} *)

All of these make sense except for the last one. If threading works on $f1$ with an empty list, why shouldn't it work on $f2$ with an empty list?

(BTW, there was no tag for threading.)

rogerl
  • 4,209
  • 3
  • 27
  • 42

1 Answers1

2

The message you see does not come from Thread but instead from the failed application of the Listable Attribute of Plus.

f2[{}, 5];

Thread::tdlen: Objects of unequal length in {}+5+{1,0} cannot be combined. >>

Listable does not work over empty lists in the way that Thread does, despite the message name being Thread::tdlen:

Attributes[foo] = Listable;

foo[{}, {1, 2, 3}]

Thread::tdlen: Objects of unequal length in foo[{},{1,2,3}] cannot be combined. >>

foo[{}, {1, 2, 3}]

If you want Thread to work in the example you give you'll need to control evaluation, e.g.

Thread[Unevaluated @ f2[{}, 5]]
{}
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • OK, but if $g$ is undefined, Thread doesn't even invoke $g$ when handed an empty list (or so it looks to me). – rogerl Feb 07 '17 at 21:47
  • @rogerl It's an evaluation thing; I added one more example that I hope is enlightening? Thread[g[{}, 3]] works precisely because g is undefined, i.e. it does not evaluate before Thread sees it. – Mr.Wizard Feb 07 '17 at 21:48
  • Well, I see that using Unevaluated works, but I really don't see why. I kind of assumed that the argument to Thread was unevaluated anyway, since Thread needs to pick the expression apart. – rogerl Feb 07 '17 at 21:51
  • @rogerl Please see the Related links (or now the Linked sidebar) I just added above. I believe your questions will be answered therein. If not feel free to ask more. :-) – Mr.Wizard Feb 07 '17 at 21:53
  • OK, thanks. Feel free to close as duplicate if you think it is. Sorry I didn't find them myself. – rogerl Feb 07 '17 at 21:54
  • @rogerl I am not voting to close as a duplicate as I do not believe either of those questions remarks upon the difference between Listable and Thread regarding {}. – Mr.Wizard Feb 07 '17 at 21:58
  • I see. The real issue is (as @george279 pointed out in his comment) that f2 does not restrict its argument type, so that both {1,2} and {} are simply passed into f2, and the threading doesn't actually take place. Now I see why your approach as well as the approach in the comment both work. Please tell me if I'm misunderstanding something. – rogerl Feb 07 '17 at 22:14
  • @rogerl That sounds right to me. – Mr.Wizard Feb 07 '17 at 22:39