8
$\begingroup$

Let's say I have

 a = Hold@{2+2} 
 b = Hold@{4+4}  

How can I get

Hold@{2+2,4+4}

ie join the two held lists ?

More generally I'm looking for a way to be able to do operations on such held lists, like being able to have Dimensions or Length, being able to Prepend or Append (answering this question would allow this) or change some parts of such lists easily.

$\endgroup$
3
  • 2
    $\begingroup$ One way would be Thread[Join[a, b]] /. {Hold[x___]} :> Hold[{x}]. $\endgroup$ Sep 11, 2013 at 15:30
  • $\begingroup$ @Leonid As with everyone else you seem to have forgotten the case where the lists in a and b are not the same length. Or perhaps that's why you didn't post this as an answer. $\endgroup$
    – Mr.Wizard
    Sep 11, 2013 at 18:04
  • 1
    $\begingroup$ @Mr.Wizard Not "like anyone else" - I proudly claim to be the first person here to make this mistake :). $\endgroup$ Sep 12, 2013 at 14:08

6 Answers 6

4
$\begingroup$

Answering the question at face value, you might use:

a = Hold@{1 + 1, 2 + 2};

b = Hold@{4 + 4};

Sequence @@@ Join[a, b] /. h_@x__ :> h@{x}
Hold[{1 + 1, 2 + 2, 4 + 4}]
$\endgroup$
8
$\begingroup$

I think there is a case to be made for not using List at all. It seems to me that it is a needless complication. Why not instead use Hold in place of List?

a = Hold[2 + 2];
b = Hold[4 + 4];

c = Join[a, b]

Append[c, Unevaluated[6 + 6]]
Hold[2 + 2, 4 + 4]

Hold[2 + 2, 4 + 4, 6 + 6]

Also:

x = Hold @@ {a, b}

Length[x]

Dimensions[x]
Hold[Hold[2 + 2], Hold[4 + 4]]

2

{2, 1}

Isn't that much cleaner? Where does it fail you?

$\endgroup$
2
  • $\begingroup$ This is cleaner indeed and was aware of this way. I happened to need for manipulating expressions before expanding them in this context mathematica.stackexchange.com/a/24596/66, and the idea seemed interesting to me. But I guess I'll have to adapt my code. Thanks anyway $\endgroup$
    – faysou
    Sep 11, 2013 at 23:24
  • $\begingroup$ @Faysal I glanced at the answer you referenced and I'll admit I don't understand it yet. Could you summarize your need for Hold[{...}] and why that seems more natural than Hold without List? $\endgroup$
    – Mr.Wizard
    Sep 12, 2013 at 0:37
6
$\begingroup$

One easy way, which does not work for lists of different length, is

a = Hold[{2 + 2}];
b = Hold[{4 + 4}];   
Thread[{a, b} /. Hold[{a___}] :> Hold[a], Hold]

What happens here is the following: first, you can use

{a, b} /. Hold[{a___}] :> Hold[a]

to get rid of the inner list braces without evaluating your expressions. Since we use {a,b} we will already get the final joined list. The only problem is that the Hold's are inside. For this, we use Thread to turn it inside out.

As pointed out by Mr.Wizard, the approach fails when the list are of different length. For such a case you could use

a = Hold[{1 + 1, 2 + 2}];
b = Hold[{4 + 4}];
Flatten[{a, b} /. List :> Hold, 2, Hold] /. Hold[expr__] :> Hold[{expr}]
$\endgroup$
2
  • $\begingroup$ This fails if the lists are not the same length, e.g. a = Hold[{1 + 1, 2 + 2}]; b = Hold[{4 + 4}]; $\endgroup$
    – Mr.Wizard
    Sep 11, 2013 at 17:05
  • $\begingroup$ @Mr.Wizard You really have to try everything, right? ;-) $\endgroup$
    – halirutan
    Sep 11, 2013 at 17:36
4
$\begingroup$

If the lists are of length 1 as in the example, you can use this:

Thread[{a, b}, Hold][[{1}, All, 1]]

For longer lists there is this:

Thread[Join @@ Thread /@ {a, b}, Hold]
$\endgroup$
5
  • $\begingroup$ This fails if the lists are not length one, e.g. a = Hold@{1 + 1, 2 + 2} $\endgroup$
    – Mr.Wizard
    Sep 11, 2013 at 17:04
  • $\begingroup$ @Mr.Wizard, good point. $\endgroup$ Sep 11, 2013 at 17:43
  • $\begingroup$ Finally an answer I can vote for. :D $\endgroup$
    – Mr.Wizard
    Sep 11, 2013 at 18:04
  • $\begingroup$ @Mr.Wizard, thank you. I shall now delete the notebook of shame and pretend like this was the most obvious thing that sprang to mind. $\endgroup$ Sep 11, 2013 at 18:12
  • $\begingroup$ Hahaha :-) I tried several that failed before realizing I could use Sequence since the example is Hold and not HoldComplete. Yours however would work even if it were, with minor change. For HoldComplete I had this bit of nasty I decided not to post: Join[a, b] /. H_[h_[x___], h_[y___]] :> H[h[x, y]] $\endgroup$
    – Mr.Wizard
    Sep 11, 2013 at 18:14
0
$\begingroup$

Edit2:Coping with my habit of missing subtleties I have tried again to correct it further.

Block[{a = Hold@{2 + 2}, b = Hold@{4 + 4}, 
  l}, {l = HoldForm[Hold[{ {s}, {d}}]] /. {s -> a /. Hold -> Defer, 
       d -> b /. Hold -> Defer}; Length[l]}
   Table[l[[i]] /. List -> Sequence, {i, 1, Length[l]}] /. 
  HoldPattern[Hold[x___]] :> Hold[{x}]

{Hold[{Sequence[2+2],Sequence[4+4]}]}

To check with @Mr.Wizard's test case of unequal lists, I am getting following output.

Block[{a = Hold@{2 + 2, 1 + 1}, b = Hold@{4 + 4}, 
  l}, {l = HoldForm[Hold[{{s}, {d}}]] /. {s -> a /. Hold -> Defer, 
       d -> b /. Hold -> Defer}; Length[l]} Table[
    l[[i]] /. List -> Sequence, {i, 1, Length[l]}] /. 
  HoldPattern[Hold[x___]] :> Hold[{x}]]

{Hold[{Sequence[2 + 2, 1 + 1], Sequence[4 + 4]}]} ReleaseHold gives {4,2,8}.

$\endgroup$
2
  • $\begingroup$ The problem is that your expression only looks as your approach works. Use FullForm to see everything. (Beside, that thing Kuba mentioned) $\endgroup$
    – halirutan
    Sep 11, 2013 at 15:43
  • $\begingroup$ yes yes..m looking into it now.Thanks for pointing out. $\endgroup$ Sep 11, 2013 at 15:45
0
$\begingroup$

A way that is quite manual but could be an inspiration for other related operations.

ReleaseAllHold[expr_,firstLevel_:0,lastLevel_:Infinity] := 
 Replace[expr, 
  (Hold|HoldForm|HoldPattern|HoldComplete)[e___] :> e, 
  {firstLevel, lastLevel}, 
  Heads -> True
 ];

JoinHeldLists[heldLists__Hold]:=
Module[{a,b,c,d},
    a={heldLists};
    b=Map[Hold,a,{1,-2}];
    c=ReleaseAllHold[b,0,-4];
    d=Join@@c;
    With[{dd=d},
        ReleaseAllHold[Hold@dd,1]
    ]
];

JoinHeldLists[Hold@{2+2},Hold@{4+4}]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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