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.

In python, if you wish to reverse a list, here is the trick:

range(10)[::-1]  => [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

Note: list[start:end:steps] is the slice method in python. The above code omitted the first two arguments.

It rings a bell in Mathematica:

Part[list, Span[start, end, step]] <=> list[[start;; end;; step]]

However this isn't gonna work in MMA (or not yet? since mine is still MMA 7)

Range[10][[;; ;; -1]]

Part::take: Cannot take positions 1 through -1 in {1,2,3,4,5,6,7,8,9,10}. >>
Part[{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 1 ;; All ;; -1]

This error message gave clues to what happened. When step length is negative, the start index should be greater than the end one - no matter in python or MMA syntax.

The problem why this didn't work lies in the omitted arguments. MMA filled them with 1 and All and then got stuck. By contrast python smartly exchanged the two.

My actual question in this is: How can I can look into the default values /optional arguments of a built-in function like Span? I can't find it in the documentations.


Give another look at the fun code: range(10)[::-1]

My implementation of this it to modify the definitions

Unprotect[Span, Part];
Part[x_List, Span[1, All, k_]] /; k < 0 := Part[x, Span[All, 1, k]];
Protect[Span, Part]

(*behold lol*)

Range[10][[;; ;; -1]]
(* {10, 9, 8, 7, 6, 5, 4, 3, 2, 1} *)

To clear the modifications:

Unprotect[Span, Part]; Clear[Span, Part]; Protect[Span, Part]

or

CompoundExpression@@ Through[{Unprotect, Clear, Protect}[Span, Part]]
share|improve this question
4  
Is there a reason that you don't want to use the Reverse command? –  Mark McClure Mar 29 '13 at 13:35
    
Nope, it's a just-because-I-could situation. And "Reverse@" is still shorter than "[[;;;;-1]]". :p –  秦紀維 Mar 29 '13 at 13:38
2  
This works: Range[10][[10 ;; 1 ;; -1]]. It's not an idiom I've used, but found it pretty easily in the documentation. –  Mark McClure Mar 29 '13 at 13:44
2  
And in case your list is of unknown length, you can change @MarkMcClure's idiom to [[-1 ;; 1 ;; -1]] to reverse it –  rm -rf Mar 29 '13 at 14:21
    
Why wouldn't you use Range[9, 0, -1]? –  m_goldberg Mar 30 '13 at 3:06
show 1 more comment

2 Answers 2

up vote 7 down vote accepted

To answer your question: In this case you could just type a fake Span call and keep it unevaluated. When you then look at the fullForm you see:

Hold[list[[ ;; ;;-1]]]//FullForm

(* Hold[Part[list,Span[1,All,-1]]] *)

what you actually called: Span[1,All,-1].

Since you now know what happens, you can catch, when someone calls Part[list_, Span[1, All, -1] and use Reverse to give the reversed list

Unprotect[Span];
Span /: Part[list_, Span[1, All, -1]] := Reverse[list];
Protect[Span]

and now your simple example works as expected

Range[10][[;;;;-1]]
(* {10,9,8,7,6,5,4,3,2,1} *)
share|improve this answer
    
Pardon me, but isn't this basically already in the question? –  Mr.Wizard Mar 29 '13 at 19:16
    
@Mr.Wizard The question was, how to find out to what Span[[;;;;-1]] is evaluated. I updated my answer later to show how to use Upvalues and Reverse. And yes, all details were already implicitly given in the question. The only part I added was how get to what list[[;;;;-1]] is evaluated. –  halirutan Mar 29 '13 at 22:20
    
is the generalization to arbitrary negative increments Reverse[list][[;;;;Abs[inc]]] or Reverse[list[[;;;;Abs[inc]]]] ? Anybody sure without trying it..? –  george2079 Mar 31 '13 at 16:49
add comment

Your python idiom can be implemented in Mathematica using Part and Span as:

Range[10][[-1;;1;;-1]]
(* {10, 9, 8, 7, 6, 5, 4, 3, 2, 1} *)

which is very similar to your python command, and doesn't require you to unprotect either Span or Part.

share|improve this answer
    
This is nice, but somehow I don't think the OP is unaware of this as he knew how to write the equivalent. Rather, this question is about low-level defaults, is it not? Isn't Span just an illustration? –  Mr.Wizard Mar 29 '13 at 19:18
1  
I don't think they're aware of negative indices, and what they wrote — [[;; ;; -1]] — is not an equivalent. I don't see this as low level defaults question, because no defaults are being used here. ;; is explicit for "all elements" (;; and All are mentioned in the Part docs), and this is just a matter of being confused by seeing 1 and All in the fullform used in the error. In other words, I don't think this has to do with mysterious defaults in the same way that Slot[1] for # is not using a hidden default of 1. –  rm -rf Mar 29 '13 at 19:40
    
Okay. By the way I meant Span[All, 1, -1] as the equivalent, which he used. –  Mr.Wizard Mar 31 '13 at 0:04
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.