2015-04-01 5 views
8

Z tego co rozumiem, ciągi znaków w Nim są w zasadzie zmienną sekwencją bajtów i są kopiowane na przypisanie.Co dokładnie są ciągi w Nim?

Biorąc pod uwagę, że Sądziłem, że sizeof powie mi (jak len) liczbę bajtów, lecz ona zawsze daje 8 na moim komputerze 64-bitowym, więc wydaje się, że trzyma wskaźnik.

Biorąc pod uwagę, że mam następujące pytania ...

  • Jaka była motywacja za kopię na przydział? Czy to dlatego, że są zmienne?

  • Czy jest jakiś czas, kiedy nie jest kopiowany po przydzieleniu? (Zakładam, że parametry funkcji nie są kopiowane.) Coś jeszcze?)

  • Czy są one zoptymalizowane w taki sposób, że są kopiowane tylko wtedy, gdy są zmutowane?

  • Czy istnieje jakaś znacząca różnica między ciągiem a sekwencją, czy też odpowiedzi na powyższe pytania można w równym stopniu zastosować do wszystkich sekwencji?

  • Coś jeszcze wartego uwagi?

Dziękujemy!

+0

dla kompletności, życie definition NIM string [na github] (https: //github.com/Araq/Nim/blob/master/lib/system.nim#L56), co może pomóc wyjaśnić, dlaczego raportuje to, co zgłasza. –

+1

@ Mike'Pomax'Kamermans: Dzięki za link, ale nie wiem, co 'string * {.magic: String.}' Próbuje mi powiedzieć. ;-) –

+0

tak, niezbyt pewny siebie, po prostu pomyślałem, że może to być dobra informacja, aby mieć w pytaniu możliwą przewagę dla ludzi lepiej w odkrywaniu, co jest od nas =) –

Odpowiedz

10

Definicja ciągów faktycznie jest w system.nim, tylko pod inną nazwą:

type 
    TGenericSeq {.compilerproc, pure, inheritable.} = object 
    len, reserved: int 
    PGenericSeq {.exportc.} = ptr TGenericSeq 
    UncheckedCharArray {.unchecked.} = array[0..ArrayDummySize, char] 
    # len and space without counting the terminating zero: 
    NimStringDesc {.compilerproc, final.} = object of TGenericSeq 
    data: UncheckedCharArray 
    NimString = ptr NimStringDesc 

więc ciąg jest surowy wskaźnik do obiektu z polem len, reserved i data. Procedury dla łańcuchów są zdefiniowane w sysstr.nim.

Semantyka przypisań ciągów została wybrana tak, aby była taka sama jak dla wszystkich typów wartości (nie ref lub ptr) w Nim domyślnie, więc można założyć, że przydziały tworzą kopię. Kiedy kopia jest niepotrzebna, kompilator może ją pominąć, ale nie jestem pewien, jak wiele to się dzieje. Przekazywanie łańcuchów do proc nie kopiuje ich. Nie ma optymalizacji, która zapobiega kopiowaniu ciągów, dopóki nie zostaną zmutowane. Sekwencje zachowują się w ten sam sposób.

Można zmienić domyślne zachowanie przypisania ciągów i seqs oznaczając je jako płytkie, a nie kopia jest wykonywana na zlecenie:

var s = "foo" 
shallow s 
+0

Dzięki def-. To bardzo pomocne i wydaje się, że "płytka" będzie przydatna. –

+2

oprócz "płytkiego", które umożliwia zachowanie "kopiuj jak wskaźnik" dla wszystkich przyszłych kopii, istnieje również operacja '' shallowCopy'', która może być używana tylko w określonych miejscach. Pod maską, żądła zarządzane w ten sposób będą dzielić ten sam przydział pamięci zliczany powtórnie. – zah

Powiązane problemy