1
$\begingroup$

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?

$\endgroup$
7
  • 1
    $\begingroup$ 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]]] $\endgroup$
    – Kuba
    Commented Apr 24, 2014 at 17:52
  • 1
    $\begingroup$ ButtonBar[Table[ With[{i = i}, ToString[myHand[[i, 1]]] <> " of " <> ToString[myHand[[i, 2]]] :> Print[myHand[[i]]]], {i, Length@myHand}]] $\endgroup$
    – Kuba
    Commented Apr 24, 2014 at 18:08
  • 1
    $\begingroup$ ButtonBar[(Row[ToString /@ #, " of "] :> Print[#]) & /@ myHand ] works as you need? $\endgroup$
    – kglr
    Commented Apr 24, 2014 at 18:08
  • 1
    $\begingroup$ Another way to force evaluation inside table: ButtonBar[Table[Row[ToString /@ j, " of "] :> Print[j] /. j -> i, {i, myHand}]] $\endgroup$
    – kglr
    Commented Apr 24, 2014 at 18:22
  • 1
    $\begingroup$ 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]]]. $\endgroup$ Commented Apr 24, 2014 at 18:28

1 Answer 1

1
$\begingroup$

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]]].)

$\endgroup$

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