Удивительные результаты для Юлии typeof - PullRequest
0 голосов
/ 16 сентября 2018

Я озадачен следующими результатами typeof в REPL Julia 1.0.0:

# This makes sense.   
julia> typeof(10)
Int64

# This surprised me.
julia> typeof(function)
ERROR: syntax: unexpected ")"

# No answer at all for return example and no error either.
julia> typeof(return)

# In the next two examples the REPL returns the input code.    
julia> typeof(in)
typeof(in)

julia> typeof(typeof)
typeof(typeof)

# The "for" word returns an error like the "function" word.
julia> typeof(for)
ERROR: syntax: unexpected ")"

Документация Julia 1.0.0 говорит для typeof "Получитьконкретный тип х. "

Пример typeof(function) - это тот, который действительно удивил меня.Я ожидал, что function будет первоклассным объектом в Джулии и будет иметь тип.Думаю, мне нужно понимать типы в Джулии.

Есть предложения?

Редактировать

Ниже приведены некоторые вопросы, касающиеся комментариев. Вот пример, основанный нанебольшая функция:

julia> function test() return "test"; end
test (generic function with 1 method)

julia> test()
"test"

julia> typeof(test)
typeof(test)

Исходя из этого примера, я ожидал, что typeof(test) вернет generic function, а не typeof(test).

1 Ответ

0 голосов
/ 16 сентября 2018

Чтобы быть ясным, я не хардкорный пользователь внутренних органов Джулии.Далее следует ответ, разработанный для (надеюсь) интуитивного объяснения того, какие функции есть у Юлии для нехардкорного пользователя.Я действительно думаю, что этот (очень хороший) вопрос мог бы также получить пользу от более технического ответа, предоставленного одним из основных разработчиков языка.Кроме того, этот ответ длиннее, чем мне бы хотелось, но я использовал несколько примеров, чтобы попытаться сделать вещи максимально интуитивно понятными.

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

Поскольку Julia v0.6 +, Function является абстрактным супертипом, во многом так же, как Number является абстрактным супертипом.Все функции, например mean, пользовательские функции и анонимные функции, являются подтипами Function, так же как Float64 и Int являются подтипами Number.

Thisструктура является преднамеренной и имеет несколько преимуществ.

Во-первых, по причинам, которые я до конца не понимаю, структурирование функций таким образом было ключом к тому, чтобы позволить анонимным функциям в Julia запускаться так же быстро, как встроенные функции изBase.См. здесь и здесь в качестве отправных точек, если вы хотите узнать больше об этом.

Во-вторых, поскольку каждая функция имеет свой собственный подтип, теперь вы можете отправлять определенныефункции.Например:

f1(f::T, x) where {T<:typeof(mean)} = f(x)

и:

f1(f::T, x) where {T<:typeof(sum)} = f(x) + 1

- это разные методы отправки для функции f1

Итак, учитывая все это, почему, например, typeof(sum) возврат typeof(sum), особенно если учесть, что typeof(Float64) возвращает DataType?Проблема здесь в том, что, грубо говоря, с синтаксической точки зрения, sum должен одновременно служить двум целям.Это должно быть как значение, например, 1.0, хотя и то, которое используется для вызова функции sum на некотором входе.Но это также должно быть имя типа, например Float64.

Очевидно, что оно не может делать оба одновременно.Так что sum ведет себя как значение.Вы можете написать f = sum ; f(randn(5)), чтобы увидеть, как оно ведет себя как значение.Но нам также нужен какой-то способ представления типа sum, который будет работать не только для sum, но и для любой пользовательской функции и любой анонимной функции.Разработчики решили пойти с (возможно) самым простым вариантом, и тип sum печатается буквально как typeof(sum), отсюда и поведение, которое вы наблюдаете.Точно так же, если я напишу f1(x) = x ; typeof(f1), это также вернет typeof(f1).

Анонимные функции немного сложнее, так как они не названы как таковые.Что мы должны сделать для typeof(x -> x^2)?На самом деле происходит то, что при создании анонимной функции она сохраняется как временная глобальная переменная в модуле Main, и ей присваивается число, которое служит ее типом для целей поиска.Поэтому, если вы напишите f = (x -> x^2), вы получите что-то вроде #3 (generic function with 1 method), а typeof(f) вернет что-то вроде getfield(Main, Symbol("##3#4")), где вы увидите, что Symbol("##3#4") - это временный тип этой анонимной функции, хранящейся в Main.(побочным эффектом этого является то, что если вы напишите код, который будет произвольно генерировать одну и ту же анонимную функцию снова и снова, вы в конечном итоге переполните память, поскольку все они на самом деле хранятся как отдельные глобальные переменные своего собственного типа).

Относя все это обратно к супертипу Function, вы заметите, что typeof(sum) <: Function возвращает true, показывая, что тип sum, то есть typeof(sum), действительно является подтипом Function.И обратите внимание также, что typeof(typeof(sum)) возвращает DataType, почти так же, как typeof(typeof(1.0)) возвращает DataType, что показывает, как sum действительно ведет себя как значение.

Теперь, учитывая все, что я сказал, все примеры в вашем вопросе теперь имеют смысл. typeof(function) и typeof(for) возвращают ошибки, как они должны, так как function и for являются зарезервированным синтаксисом. typeof(typeof) и typeof(in) правильно возвращают (соответственно) typeof(typeof) и typeof(in), поскольку typeof и in являются обеими функциями. Обратите внимание, что typeof(typeof(typeof)) возвращает DataType.

...