2016-07-09 2 views
3

Юлия позволяет легко построение массивов, на слух синтаксис:Руководство умозаключения типа в Джулии

A = [ sqrt(i)^2+j for i in 0:10, j in 1:3 ] 

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

Иногда, однако, предпочтительнее вложенный цикл. Это может быть связано с тем, что массив имеет много измерений или потому, что длина второго итерабельного зависит от первого, или потому что выражение сложное и вычисление имеет побочные эффекты.

В этих случае приведенный выше код может быть расширен в

T = ??? 
A = Array{T}(11,3) 
for i in 0:10 
    for j in 1:3 
    A[i,j] = sqrt(i)^2 + j 
    end 
end 

Как T быть вычислены в простой, легко читаемой, легко обслуживаемой моде? Есть ли способ вручную вызвать механизм вывода типа, используемый под капотом списков? Решения я считаю неудовлетворительными являются:

T = Float64 # Not my job to do the compiler's work... 
T = typeof(sqrt(0)^2+1) # Or is the argument of typeof not evaluated in this case? 

Что-то вдоль линии C++ decltype механизма возможно?

+0

Если функции, которые вы используете, являются чистыми функциями, а компилятор знает, что они есть, то компилятор должен иметь возможность поднять вычисления во второй строке во время компиляции. –

ответ

3

На самом деле, все не так просто. Понятия, используемые для выбора типа элемента с использованием вывода типа, но, насколько я понимаю, отошли от этого.

Теперь (я считаю), тип начального элемента берется как тип первого элемента. При необходимости тип элемента расширяется, и массив перераспределяется. Если результирующий тип элемента является конкретным типом, который может быть выведен по типу вывода, результирующий код по-прежнему эффективен, как если бы тип элемента был основан на прямом указании типа.

Причина, по которой эти соображения ушли от прямой зависимости от вывода типа, заключается в том, что она предназначена для оптимизации, чтобы сделать код Джулии быстрее, а не частью семантики Юлии. На практике джулия не всегда может вывести жесткий тип, и результаты вывода могут варьироваться в зависимости от версий julia, поэтому нежелательно, чтобы поведение кода зависело от него (хотя производительность, конечно же, будет).

Учитывая вашу первоначальную проблему: я часто нахожу, что она делает код более чистым с меньшими неожиданностями, если вы позволите пользователю указать тип результата T в таком случае. Механизм, который я описал для понимания, также используется map (и более или менее на broadcast, но до сих пор они не совсем последовательны), но он не подвергался непосредственно пользователям (не знаю, было бы ли смысл Сделай так).

+0

Если я правильно понимаю вас, второе предложение в моем сообщении похоже на то, как понимание списка делает что-то? Я благодарен за то, что дубликат не может быть реализован на языке, где типы возвращаемых данных известны только во время выполнения. Тем не менее, я уверен, вы понимаете мое разочарование в этой ситуации, которая появляется снова и снова в моем коде ... – krcools

1

Существует неопубликованный недокументированный Base.return_types. Он много используется в тестах, поэтому выполните поиск в каталоге тестов, чтобы найти способы использования. Обратите внимание на ответ Тойвио и будьте готовы, чтобы он мог отказаться и просто вернуть Any для того же выражения в новой версии Julia.