Ответ 1
Лучший способ - сохранить их в Hold
, а не List
, например:
In[255]:= f[x_] := x^2;
lh = Hold[Plus[1, 1], Times[2, 3], f[2]]
Out[256]= Hold[1 + 1, 2 3, f[2]]
Таким образом, у вас есть полный контроль над ними. В какой-то момент вы можете вызвать ReleaseHold
для их оценки:
In[258]:= [email protected]
Out[258]= Sequence[2, 6, 4]
Если вы хотите получить результаты в списке, а не Sequence
, вместо этого вы можете использовать только [email protected]@lh
. Если вам нужно оценить конкретный, просто используйте Part
, чтобы извлечь его:
In[261]:= lh[[2]]
Out[261]= 6
Если вы настаиваете на своей конструкции, вот путь:
In[263]:= l:={Plus[1,1],Times[2,3],f[2]};
Hold[l]/.OwnValues[l]
Out[264]= Hold[{1+1,2 3,f[2]}]
ИЗМЕНИТЬ
Если у вас есть некоторые функции/символы с UpValues
, которые могут оцениваться даже внутри Hold
, вы можете использовать HoldComplete
вместо Hold
.
EDIT2
Как указал @Mr.Wizard в другом ответе, иногда вам может быть удобнее иметь Hold
, обернутую вокруг отдельных элементов в вашей последовательности. Мой комментарий здесь заключается в том, что полезность обеих форм усиливается, когда мы понимаем, что очень легко превратить одно в другое и обратно. Следующая функция разделит последовательность внутри Hold
на список удерживаемых элементов:
splitHeldSequence[Hold[seq___], f_: Hold] := List @@ Map[f, Hold[seq]]
например,
In[274]:= splitHeldSequence[Hold[1 + 1, 2 + 2]]
Out[274]= {Hold[1 + 1], Hold[2 + 2]}
объединение их обратно в один Hold
еще проще - просто Apply
Join
:
In[275]:= Join @@ {Hold[1 + 1], Hold[2 + 2]}
Out[275]= Hold[1 + 1, 2 + 2]
Две различные формы полезны в разных обстоятельствах. Вы можете легко использовать такие вещи, как Union
, Select
, Cases
в списке удерживаемых элементов, не задумываясь над оценкой. Как только вы закончите, вы можете объединить их обратно в один Hold
, например, для подачи как неоцененной последовательности аргументов некоторой функции.
РЕДАКТИРОВАТЬ 3
По запросу @ndroock1, здесь приведен конкретный пример. Настройка:
l = {1, 1, 1, 2, 4, 8, 3, 9, 27}
S[n_] := Module[{}, l[[n]] = l[[n]] + 1; l]
Z[n_] := Module[{}, l[[n]] = 0; l]
размещение функций в Hold
:
In[43]:= held = Hold[Z[1], S[1]]
Out[43]= Hold[Z[1], S[1]]
Вот как выглядит функция exec
:
exec[n_] := MapAt[Evaluate, held, n]
Теперь
In[46]:= {exec[1], exec[2]}
Out[46]= {Hold[{0, 1, 1, 2, 4, 8, 3, 9, 27}, S[1]], Hold[Z[1], {1, 1, 1, 2, 4, 8, 3, 9, 27}]}
Обратите внимание, что исходная переменная held
остается неизменной, так как мы работаем над копией. Также обратите внимание, что исходная настройка содержит изменяемое состояние (l
), которое не очень идиоматично в Mathematica. В частности, имеет смысл порядок оценок:
In[61]:= Reverse[{exec[2], exec[1]}]
Out[61]= {Hold[{0, 1, 1, 2, 4, 8, 3, 9, 27}, S[1]], Hold[Z[1], {2, 1, 1, 2, 4, 8, 3, 9, 27}]}
Является ли это желательным, зависит от конкретных потребностей, я просто хотел указать на это. Кроме того, в то время как вышеприведенный exec
реализован в соответствии с запрошенной спецификацией, он неявно зависит от глобальной переменной l
, которую я считаю плохой практикой .
Альтернативный способ хранения функций, предлагаемых @Mr.Wizard, может быть достигнут, например. как
В [63]: = listOfHeld = splitHeldSequence [проведено]
Out [63] = {Удерживать [Z 1], Удерживать [S 1]}
и здесь
In[64]:= execAlt[n_] := MapAt[ReleaseHold, listOfHeld, n]
In[70]:= l = {1, 1, 1, 2, 4, 8, 3, 9, 27} ;
{execAlt[1], execAlt[2]}
Out[71]= {{{0, 1, 1, 2, 4, 8, 3, 9, 27}, Hold[S[1]]}, {Hold[Z[1]], {1, 1, 1, 2, 4, 8, 3, 9, 27}}}
Те же комментарии о изменчивости и зависимости от глобальной переменной также идут здесь. Эта последняя форма также более подходит для запроса типа функции:
getType[n_, lh_] := lh[[n]] /. {Hold[_Z] :> zType, Hold[_S] :> sType, _ :> unknownType}
например:
In[172]:= getType[#, listOfHeld] & /@ {1, 2}
Out[172]= {zType, sType}