Почему есть предупреждение не использовать system.cmp[string] для сравнения строк Nim

В стандартной библиотеке Nim есть предупреждение:

 sort(myIntArray, system.cmp[int])

 # do not use cmp[string] here as we want to use the specialized
 # overload:
 sort(myStrArray, system.cmp)

Может ли кто-нибудь дать более подробное объяснение этому?

Что я пробовал

  1. Глядя в исходный код

Похоже, что может быть две реализации сортировки, обычная и специализированная для сравнения строк, но поиск в источнике здесь Я не могу найти такой специализации.

  1. Эксперименты с компилятором

Я попытался написать следующую программу:

import algorithm

var strArray: array[4,string]  = ["a","ab","abcd","abc"]

sort(strArray, system.cmp[string])
# sort(strArray, system.cmp)

for x in strArray:
  echo x

и попробовал оба способа сделать сравнение. Однако, когда я сравнил сгенерированный код C, не обнаружил существенных различий. Вывод fc показан ниже, но на мой взгляд это просто незначительные изменения:

Comparing files NIMCACHE\testsorta.c and NIMCACHE\TESTSORT.C
***** NIMCACHE\testsorta.c
typedef struct {
N_NIMCALL_PTR(NI, ClPrc) (NimStringDesc* x_91042, NimStringDesc* y_91044, void*
ClEnv);
void* ClEnv;
} TY91048;
typedef N_CLOSURE_PTR(NI, TMP153) (NimStringDesc* x_91025, NimStringDesc* y_9102
7, void* ClEnv);
struct  tcell44933  {
***** NIMCACHE\TESTSORT.C
typedef struct {
N_NIMCALL_PTR(NI, ClPrc) (NimStringDesc* x_91054, NimStringDesc* y_91056, void*
ClEnv);
void* ClEnv;
} TY91060;
typedef N_CLOSURE_PTR(NI, TMP153) (NimStringDesc* x_91037, NimStringDesc* y_9103
9, void* ClEnv);
struct  tcell44933  {
*****

***** NIMCACHE\testsorta.c
N_NIMCALL(void, genericAssign)(void* dest, void* src, TNimType* mt);
N_NIMCALL(void, sort_91029)(NimStringDesc** a_91037, NI a_91037Len0, TY91048 cmp
_91047, NU8 order_91050);
N_NIMCALL(void, merge_91090)(NimStringDesc** a_91098, NI a_91098Len0, NimStringD
esc** b_91106, NI b_91106Len0, NI lo_91110, NI
m_91112, NI hi_91114, TY91048 cmp_91122, NU8 order_91125);
N_NIMCALL(NI, cmp_4517)(NimStringDesc* x, NimStringDesc* y);
N_NIMCALL(NimStringDesc*, copyStringRC1)(NimStringDesc* src);
***** NIMCACHE\TESTSORT.C
N_NIMCALL(void, genericAssign)(void* dest, void* src, TNimType* mt);
N_NIMCALL(NI, cmp_91024)(NimStringDesc* x_91028, NimStringDesc* y_91030);
N_NIMCALL(void, sort_91041)(NimStringDesc** a_91049, NI a_91049Len0, TY91060 cmp
_91059, NU8 order_91062);
N_NIMCALL(void, merge_91102)(NimStringDesc** a_91110, NI a_91110Len0, NimStringD
esc** b_91118, NI b_91118Len0, NI lo_91122, NI
m_91124, NI hi_91126, TY91060 cmp_91134, NU8 order_91137);
N_NIMCALL(NimStringDesc*, copyStringRC1)(NimStringDesc* src);
*****

***** NIMCACHE\testsorta.c
NIM_EXTERNC N_NOINLINE(void, testsortInit)(void) {
        TY91048 LOC1;
        nimfr("testsort", "testsort.nim")
***** NIMCACHE\TESTSORT.C
NIM_EXTERNC N_NOINLINE(void, testsortInit)(void) {
        TY91060 LOC1;
        nimfr("testsort", "testsort.nim")
*****

***** NIMCACHE\testsorta.c
        memset((void*)(&LOC1), 0, sizeof(LOC1));
        LOC1.ClPrc = ((TMP153) (cmp_4517)); LOC1.ClEnv = NIM_NIL;
        sort_91029(strarray_91015, 4, LOC1, ((NU8) 1));
        {
***** NIMCACHE\TESTSORT.C
        memset((void*)(&LOC1), 0, sizeof(LOC1));
        LOC1.ClPrc = ((TMP153) (cmp_91024)); LOC1.ClEnv = NIM_NIL;
        sort_91041(strarray_91015, 4, LOC1, ((NU8) 1));
        {
*****

person Peter de Rivaz    schedule 22.02.2015    source источник


Ответы (1)


proc cmp[T](x, y: T): int

proc cmp(x, y: string): int

Сравните proc для строк. Более эффективен, чем универсальная версия.

В этом разница. cmp(s1, s2) более эффективен, чем cmp[string](s1, s2).

Причина, по которой вы не видите никакой разницы в сгенерированном коде, заключается в том, что в одной версии cmp(string, string) превратилось в функцию C, а в другой — обобщенный экземпляр, созданный как cmp[string](string, string) в функцию C, и их сигнатуры абсолютно одинаковы. Следует искать отличия в телах этих функций, которые должны быть в system.c.

person Oleh Prypin    schedule 22.02.2015
comment
Это идеально, спасибо! Вы совершенно правы, если я сравню stdlib_system.c, то я действительно увижу медленную версию, сгенерированную, если я использую неправильную функцию - теперь все это имеет смысл :) - person Peter de Rivaz; 22.02.2015