I have built a function which carries out a set of operations given two parameters. The function looks as follows:

playingHand[Player_, Name_String] :=
 Row[{Style[Name <> ":", FontSize -> 48, FontFamily -> "Calibri"],
   If[Player == {}, {Style["Not playing", 48, Gray, 
      FontFamily -> "Calibri"]},
       With[{i = i},
        Player[[i, 3]] :>
         {AppendTo[discardPile, Player[[i]]], 
          Player = Delete[Player, i]}],
       {i, Length@Player}]]}]]

The gist of this function is that as its first input it takes a list, which looks something like:

enter image description here

and displays the third elements of each list within that list:

enter image description here

It also makes these images clickable, so that when one of these cards is clicked, it should disappear from player1 and get added to an initially empty list called discardPile. So far so good. When I run this function by itself without the defined function, namely like this:

   With[{i = i},
    player1[[i, 3]] :>
     {AppendTo[discardPile, player1[[i]]], 
      player1 = Delete[player1, i]}],
   {i, Length@player1}]] // Dynamic

it works like a treat. The cards are clickable and they disappear from the ButtonBar as soon as they are clicked and added to discardPile. When I try to do the same from within the function though, namely playingHand[player1, "Aron"] // Dynamic it suddenly stops working. A Set::shape error message comes up warning that two lists are not the same length, and although it does add the card to discardPile, it does not remove it from player1. So:

  1. What is wrong with this function and why won't it delete the card from the list when it is clicked, and
  2. How come the same error does not occur when I run the function directly without calling it by its function name?
  • 1
    $\begingroup$ Please provide a self-contained example. $\endgroup$ – Mr.Wizard May 3 '14 at 22:52
  • 1
    $\begingroup$ This question has an answer here $\endgroup$ – m_goldberg May 4 '14 at 1:25

You need to set a Hold-ish attribute on playingHand to preserve your first parameter as a symbol when it is replaced into the body of the function.

SetAttributes[playingHand, HoldFirst];
playingHand[Player_, Name_String] := ...

You have to do this because your function body is assigning to Player, and you can't assign to the explicit list that gets inserted for Player when your function is invoked. For example, something basically like this is happening there:

In[11]:= {1, 2, 3} = Delete[{1, 2, 3}, 2]

During evaluation of In[11]:= Set::shape: Lists {1,2,3} and {1,3} are not the same shape. >>

Out[11]= {1, 3}
  • $\begingroup$ you are a genius. I am eternally grateful to you! $\endgroup$ – Aron May 3 '14 at 23:41

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