Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a set of symbolic algebraic expressions that I'm trying to get some speed into. To illustrate the issue, I'll use a simple form like { k0 X, k1 Y, k1 Z}, where each term is large and complicated. By random walk, I've arrived at a promising form

{ r0 X, r1 Y,r1 Z}/.r0->k0 /.r1->k1

which is faster than the original, but with my particular set of expressions, it turns out that a function is faster:

{#[[1]] X, #[[2]] Y, #[[2]] Z}&@{k0, k1}

The expressions are large, making substitutions by hand time consuming and error prone, so I set out to replace the k s with a rule like

{k0->#[[1]],k1->#[[2]]}

I was surprised that this wasn't a straightforward operation, k0 being replaced by 1 instead of the intended #[[1]]. I thrashed around for a bit, eventually finding the odd (to me) result that

{#[[1]], #[[2]]}//FullForm

Gives

List[ 1, Part[Slot[1],2]]

Can anyone suggest a way of thinking in which this makes sense? Is there any place in the design for Part[Slot[1],1] ? I worked around it with a hack:

{#[[2]] X, #[[3]] Y, #[[3]] Z}&@{Null, k0, k1}

which works but is ugly to say nothing of embarrassing.

Thanks in advance.

share|improve this question
    
According to the manual page, # is a synonym for Slot[1]. Thus, #[[1]] means the first element of Slot[1] which manifestly is the object inside []; namely, 1. #[[2]] means the second element of Slot[1]; it does not exist. Not only does MMA spit it back out unevaluated (as Part[Slot[1],2] in full form), but it also issues a Part::partd message, "Part specification Slot[[1]] is longer than depth of object." –  whuber Nov 13 '12 at 6:48
    
Hi Fred, glad to see you here and welcome to Mathematica.SE! Please consider registering your account so that any upvotes you get on this question are added to those you might get on future questions and answers. That way, over time you will be able to do more on the site (post graphics, edit things, etc). –  Sjoerd C. de Vries Nov 13 '12 at 8:11
    
A way you could accomplish what you want is {k0}&/.{k0->Hold[#[[1]]]}//ReleaseHold. I don't think it's a good idea though! –  sebhofer Nov 13 '12 at 23:21
    
Thanks everyone for the comments and the answer. Up until now, i had used Prefix and Apply agnostically, but this case clinches the argument in favor of Apply. The k->#1 etc. works without surprise. @VF1 - I follow your explanation for the title result, but it scares me enough that I plan to avoid any tricks with Slot from now on. –  Fred Klingener Nov 15 '12 at 3:26
    
@FredKlingener I hope you don't stop using pure functions because of this - it would be a shame. They have their uses. –  VF1 Nov 15 '12 at 3:32
add comment

1 Answer

This seems very unclear. Have you tried Apply? It's better (more readable) for working with elements of lists in pure functions.

{#1 X, #2 Y, #2 Z}&@@{k0, k1}

Note that the Slot[1][[1]]//FullForm == 1 peculiarity arises from the fact that the 1 is the first expression inside Slot. You'll notice that, e.g., f[1][[1]] returns 1, and that Slot[2][[1]] returns 2.

While I encourage you to use Apply (which is @@) for clarity, another solution does exist. By assigning a symbol to the pure function rather than a numbered slot (which evaluates to 1 with Part), you can get around the premature evaluation:

Function[a,{a[[1]] X, a[[2]] Y, a[[2]] Z}]@{k0, k1}

This is functionally equivalent to what your desired result is, but, again, less clear than Apply.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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