Julia - изменяемая структура с атрибутом, который является функцией и @code_warntype - PullRequest
0 голосов
/ 25 октября 2018

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

mutable struct Class_example
    function_with_arguments::Function
    some_attribute::Int
    function Class_example() new() end
    function Class_example(function_wa::Function, some_a::Int)
        this = new()
        this.function_with_arguments = function_wa
        this.some_attribute = some_a
        this
    end
end

Я также хочу выполнить действие с этой изменяемой структурой:

function do_action_on_class(Class::Class_example)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end

Затем я определяю функцию, которая должна быть моим атрибутом класса:

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end

Наконец, function_whith_arguments будет запускаться огромное количество раз во всем моем проекте, этотолько минимальный пример, поэтому я хочу, чтобы весь этот код был очень быстрым.Вот почему я использую @code_warntype в соответствии с документацией Джулии Советы по повышению производительности

Однако @code_warntype сообщает мне это

body::Any
15 1 ─ %1 = (Base.getfield)(Class, :function_with_arguments)::Function
getproperty
%2 = (Base.getfield)(Class, :some_attribute)::Int64
%3 = (%1)(%2, 2.0, true)::Any                                     │ 
return %3              

Здесь ::Function и два ::Any выделены красным, что указывает на то, что Юлия может улучшить производительность кода с лучшей реализацией.Так что это за правильная реализация?Как мне объявить мой атрибут function_whith_arguments как тип Function в моей изменяемой структуре?

Весь код скомпилирован:

mutable struct Class_example
    function_with_arguments::Function
    some_attribute::Int
    function Class_example() new() end
    function Class_example(function_wa::Function, some_a::Int)
        this = new()
        this.function_with_arguments = function_wa
        this.some_attribute = some_a
        this
    end
end


function do_action_on_class(Class::Class_example)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end

function main()
    class::Class_example = Class_example(do_something_function, 4)
    @code_warntype do_action_on_class(class)
end

main()

1 Ответ

0 голосов
/ 25 октября 2018

Это будет эффективно (хорошо выведено).Обратите внимание, что я только изменил (и переименовал) тип.

mutable struct MyClass{F<:Function}
    function_with_arguments::F
    some_attribute::Int
end


function do_action_on_class(Class::MyClass)
    return Class.function_with_arguments(Class.some_attribute ,2.0, true)
end

function do_something_function(arg1::Int, arg2::Float64, arg3::Bool)
    if arg2 < 5.0
        for i in 1:arg1
            # Do Something Interesting
            @show arg3
        end
    end
    return 1
end

function main()
    class::MyClass = MyClass(do_something_function, 4)
    @code_warntype do_action_on_class(class)
end

main()

Что я сделал?

  • Если вы заботитесь о производительности, никогда не должно иметь полей абстрактного типа и isabstracttype(Function) == true.Вместо этого вам следует параметризовать этот тип полей (F выше, это может быть любая функция. Обратите внимание, что isconcretetype(typeof(sin)) == true).Таким образом, для любого конкретного экземпляра MyCall точный конкретный тип каждого поля известен во время компиляции.

  • Не имеет значения для производительности, но: нет необходимости в конструкторе, который простоприсваивает все аргументы всем полям.Такой конструктор определен по умолчанию неявно.

Подробнее о параметрических типах можно прочитать здесь .

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

...