1

I am trying to make a ButtonBar that prints the name of the card in question.

enter image description here

What I have so far is as follows:

myHand = {{1, "Spades"}, {4, "Hearts"}, {5, "Clubs"}, {8, 
   "Spades"}, {9, "Hearts"}, {9, "Spades"}, {11, "Spades"}};

ButtonBar[Table[
  ToString[myHand[[i, 1]]] <> " of " <> ToString[myHand[[i, 2]]] :>
   Print[myHand[[i]]],
  {i, Length@myHand}]
 ]

However, instead of working as expected and printing out the name of the card in question, it always prints out {9, Hearts}. When I looked into the FullForm for this it made sense why:

ButtonBar[List[RuleDelayed["1 of Spades", Print[Part[myHand, i]]], 
 RuleDelayed["4 of Hearts", Print[Part[myHand, i]]], 
 RuleDelayed["5 of Clubs", Print[Part[myHand, i]]], 
 RuleDelayed["8 of Spades", Print[Part[myHand, i]]], 
 RuleDelayed["9 of Hearts", Print[Part[myHand, i]]], 
 RuleDelayed["9 of Spades", Print[Part[myHand, i]]], 
 RuleDelayed["11 of Spades", Print[Part[myHand, i]]]]]

The rule is to print out i, not the actual number. How can I remedy this so that my Table generates a list of actual rules without holding the is back from being evaluated in the Table?

Aron
  • 1,722
  • 1
  • 12
  • 30
  • 1
    RuleDelayed has an attribute HoldRest you have tu use Evaluate (not always possible) or inject i with With like With[{i = i}, "string":>list[[i]]] – Kuba Apr 24 '14 at 17:52
  • Ok so I tried all of those, but Evaluate didn't work, nor did With. Any other ideas? – Aron Apr 24 '14 at 18:05
  • 1
    ButtonBar[Table[ With[{i = i}, ToString[myHand[[i, 1]]] <> " of " <> ToString[myHand[[i, 2]]] :> Print[myHand[[i]]]], {i, Length@myHand}]] – Kuba Apr 24 '14 at 18:08
  • 1
    ButtonBar[(Row[ToString /@ #, " of "] :> Print[#]) & /@ myHand ] works as you need? – kglr Apr 24 '14 at 18:08
  • @Kuba, thank you! I was inserting the With at the wrong place. @kguler, your code also works - though looks a bit more complicated – Aron Apr 24 '14 at 18:12
  • 1
    Another way to force evaluation inside table: ButtonBar[Table[Row[ToString /@ j, " of "] :> Print[j] /. j -> i, {i, myHand}]] – kglr Apr 24 '14 at 18:22
  • 1
    I think, the easiest is to use injector pattern: Range[Length[myHand]] /. i_Integer :> (ToString[myHand[[i, 1]]] <> " of " <> ToString[myHand[[i, 2]]]) :> Print[myHand[[i]]]. – Leonid Shifrin Apr 24 '14 at 18:28

1 Answers1

1

You can inject the values of the iterator variable into held expressions using With as suggested in the comments. Alternatively, you can use

ButtonBar[Table[Row[ToString /@ #, " of "] :> Print[#] &[i], {i, myHand}]] 

or

ButtonBar[Table[Row[ToString /@ j, " of "] :> Print[j] /. j -> i, {i, myHand}]]

You can also create the list of buttons you need without Table:

ButtonBar[(Row[ToString /@ #, " of "] :> Print[#]) & /@ myHand ]

(where Row[ToString /@ {9,Hearts}, " of "], for example gives the same output as your ToString[myHand[[5, 1]]] <> " of " <> ToString[myHand[[5, 2]]].)

kglr
  • 394,356
  • 18
  • 477
  • 896