2011-12-22 15 views
6

Od czasu do czasu lubimy sprawdzać, jak zdefiniowane są niektóre funkcje System` (gdy są napisane w Mathematica). To pytanie dotyczy najlepszego sposobu na zrobienie tego.Jaki jest najlepszy sposób odczytu kodu z już zdefiniowanej funkcji (szczególnie z kontekstu Systemu)?

Punkty do pamiętać:

  • couse ReadProtected musi najpierw zostać usunięte.

  • Winsins zazwyczaj muszą być użyte przynajmniej raz, zanim zostaną załadowane do jądra. Czy pojedyncze proste wywołanie zwykle wystarcza do tego, gdy mają rozszerzoną funkcjonalność (np. Poprzez opcje)?

  • Information (??) nadaje definicję w trudnym do odczytania formacie (bez wcięcia, a wszystkie prywatne nazwy kontekstowe zostały dodane). Jaki jest najlepszy sposób na pozbycie się nazw kontekstowych i uzyskanie sformatowanego kodu?

    Jednym z pomysłów na pozbycie się pewnych kontekstów jest Block[{$ContextPath = Append[$ContextPath, "SomeContext`Private`"], Information[symbol]]. Kod może być automatycznie formatowany za pomocą Workbencha. Niektóre problemy pozostają, np. Information nie cytuje ciągów znaków, uniemożliwiając skopiowanie kodu do Workbencha.

Ogólnie, jestem zainteresowany tym, jak ludzie to zrobić, jakich metod używają, aby kod builtins jak łatwe do odczytania, jak to możliwe.

Przypadek użycia: Na przykład niedawno wykopałem kod RunThrough, gdy dowiedziałem się, że po prostu nie działa on w systemie Windows XP (okazuje się, że nie podaje nazw plików tymczasowych, gdy ścieżka do nich zawiera spacje).


Aktualizacja:It appears że kiedyś funkcja definicje drukowania bez kontekstu poprzedzany, Developer`ContextFreeForm, ale to nie działa dłużej w nowszych wersjach.

+0

Możesz pozbyć się prywatnych nazw kontekstów, wpisując kontekst przed wywołaniem '?? '. – cah

Odpowiedz

7

Odnośnie ładnego drukowania: Poniżej znajduje się kod, który bardzo schematyczny pokazać opiera się na odpowiedź od @ Mr.Wizard że kilka prostych zasad może przejść długą drogę w kierunku poprawy czytelności kodu:

Internal`InheritedBlock[{RunThrough}, 
    Unprotect[RunThrough]; 
    ClearAttributes[RunThrough, ReadProtected]; 
    Block[{$ContextPath = Append[$ContextPath, "System`Dump`"]}, 
     With[{boxes = [email protected] DownValues[RunThrough]}, 
     CellPrint[Cell[BoxData[#], "Input"]] &[ 
      boxes /. 
      f_[left___, "\[RuleDelayed]", right___] :> 
       f[left, "\[RuleDelayed]", "\n", right] //. 
      { 
      RowBox[{left___, ";", next : Except["\n"], right___}] :> 
       RowBox[{left, ";", "\n", "\t", next, right}], 
      RowBox[{sc : ("Block" | "Module" | "With"), "[", 
       RowBox[{vars_, ",", body_}], "]"}] :> 
       RowBox[{sc, "[", RowBox[{vars, ",", "\n\t", body}], "]"}] 
      }]]]] 

to na pewno nie jako ogólne rozwiązanie (w szczególności nie będą dobrze pracować głęboko zagnieżdżony kod funkcjonalnego bez wiele oddzielne oświadczenia), ale jestem pewien, że można to poprawić i uogólnić bez większych problemów, aby objąć wiele spraw S zainteresowania.

+0

Działa to bardzo dobrze w praktyce na tym ograniczonym przykładzie! @ Mr.Wizard Znalazłem [interesującą wizualizację kodu programu M] (http://taliesinb.net/quicksort-in-61-characters), niestety nie podaje kodu, aby go wyprodukować. – Szabolcs

+0

@Szabolcs: Interesujące. Czy próbowałeś skontaktować się z autorem? –

+0

@ Mr.Wizard Tak, brak odpowiedzi do tej pory. Ale to sezon wakacyjny. – Szabolcs

5

Dobre pytanie, ponieważ nie sądzę, abym już to widział.

Zasadniczo robię to samo co opisane. Można uzyskać nieco inny wydruk z Definition, a więcej informacji o FullDefinition:

Unprotect[RunThrough]; 

ClearAttributes[RunThrough, ReadProtected] 

Block[{$ContextPath = Append[$ContextPath, "System`Dump`"]}, 
    Print @ FullDefinition @ RunThrough 
] 
+0

+1 Nie zdawałem sobie sprawy, że możesz manipulować ścieżką kontekstu, aby osiągnąć ten sam cel (pozbycia się nazw wziętych z kontekstu prywatnego). Zawsze używałem BeginContext.Sądzę, że pozostała część pytania do OP ocenia "jak ładnie drukujesz kod Mathematica?" Jedyny znany program do formatowania kodu źródłowego znajduje się w menu kontekstowym edytora Wolfram Workbench. – cah

+0

@cah Jest jeszcze jeden ważny problem. Spróbuj skopiować kod "RunThrough" do Workbencha, a zobaczysz, że daje błędy składni. Dzieje się tak dlatego, że cudzysłowy wokół ciągów nie są drukowane, a ta zawiera nawet parę na ciągach zawierających tylko spacje. Kolejną rzeczą jest: jak zdobyć źródło na formie do wklejenia? Metoda '$ ContextPath' wspomniałam również w moim pytaniu w małym typie. – Szabolcs

+0

@cah Co 'Begin' i przyjaciele robią to po prostu modyfikowanie' $ ContextPath', nic więcej. – Szabolcs