2015-11-13 4 views
2

Я хочу использовать объект в Julia, который может быть инициализирован функцией. Это как указатель на функцию в C.
julia: объект функции

Вот моя цель:

У меня есть сценарий Юли и модуль Джулии.

В этом скрипте у меня есть массив.
Модуль должен иметь возможность добавлять некоторые элементы в этот массив.

#script 
liste = Int64[] 
function addElement(e) 
    liste.push(e) 
end 
include("path/mymodule.jl") 
myModule.setAddElementFunc(addElement) 
myModule.execute() # error: wrong number of parameter 



#mymodule.jl 

module myModule 
export setAddElementFunc 
export execute 

addElementFunc =()->() 

funciton setAddElementFunc(fn) 
    addElementFunc = fn 
end 

function execute() 
    addElementFunc(3) 
end 

end 

В основном, моя идея:
в модуле, мы ничего не можем, НО add делать. Мне нужно сделать такую ​​структуру, потому что моя задача - кодировать julia-скрипт, а некоторые другие будут кодировать модуль. Поэтому я хочу ограничить его право держать список в безопасности, в этом случае он может просто добавить элементы.

+0

'глобального addElementFunc = fn', а также' функция выполнения (Arg :: Кортеж) addElementFunc (аргумент ...) end' –

+0

@RezaAfzalan Есть ли другой способ, кроме 'арга .. .'. Я предпочитаю использовать объект как указатель функции в C. – Yves

+0

'addElementFunc (arg ...) === apply (addElementFunc, arg)' –

ответ

1

Хотя @David согласен правильно, я хотел бы указать на полезность ключевого слова global. Мне нравится думать об этом здесь как CPP this Подобное ключевое слово в Julia-Lang.

module test 
    addMsgFunc=()->() 
    function getAddMsgFunc(fn) 
    global addMsgFunc = fn 
    end 
    function show() 
    println("xxxxx") 
    end 
end 
julia> addMsgFunc 
ERROR: UndefVarError: addMsgFunc not defined 
julia> test.addMsgFunc(); 
julia> test.getAddMsgFunc(test.show); 
julia> test.addMsgFunc() 
xxxxx 
julia> addMsgFunC# Its in global but in another scope 
ERROR: UndefVarError: addMsgFunc not defined 
julia> test.addMsgFunc=()->() # You cant assign to it normally 
ERROR: cannot assign variables in other modules 
+0

Большое спасибо. Остается только один вопрос: если show() имеет один параметр, как изменить 'addMsgFunc =() ->()'? – Yves

+1

нет проверки типа на уровне модуля, поэтому не думайте об этом как о классе 'cpp', а' addMsgFunc =() ->() 'не работает как инициализатор, на самом деле вам это не нужно. Я думаю, что ваш вопрос является признаком непонимания. –

+0

Использование такого глобального подхода, на мой взгляд, очень плохая идея. Это «un-Julian» и будет медленным. Это также очень затрудняет рассуждение о коде, поскольку любой может изменить глобальную переменную из любого места. Возможно, что вы ищете, чтобы встроить функцию внутри пользовательского типа? –

1

Не совсем понятно, что вы хотите сделать. Одна из возможностей заключается в следующем:

function getAddMsgFunc(fn) 
    fn # just return the function that is passed in 
end 

function my_show() 
    println("xxxxx") 
end 

addMsgFunc = getAddMsgFunc(my_show) 

addMsgFunc() 

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

2

Для создания нового типа в Джулии мы можем сделать что-то вроде

type MyArray{T} 
    elements::Vector{T} 
    my_value::Int 
end 

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

v = MyArray([3, 5], 17) 

В Джулии, функции делают не живут внутри объектов, а методы, определенные вне объектов. В этом смысле объекты в Julia похожи на структуры в C, за исключением того, что они могут (и, как правило, должны) быть параметризованы по типу, как в этом примере ({T}).

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

push!(x::MyArray, value) = push!(x.elements, value) 

Теперь вы можете сделать

push!(v, 4) 

, чтобы добавить значение 4 к вашему объекту.

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

+0

Большое спасибо. Понял тебя. Я прочитал несколько руководств, но я до сих пор не знаю, как объявить объект функции, например, указатель на функцию в C. – Yves

+0

. Теперь мне это нравится: в модуле 'function execute (fn1, fn2)'; В скрипте я могу вызвать 'myModule.execute (addElement, setElement)', 'addElement' и' setElement' - две функции в скрипте. Оно работает. Поэтому мне больше не нужен указатель на функцию. Если вы знаете, как объявить указатель на функцию в Julia, скажите мне: D большое спасибо. – Yves

0

«Функциональный указатель» - это сложная конструкция C, которая необходима, потому что нет другого способа иметь другое имя, которое вы можете использовать для обозначения функций.

В Джулии вы просто буквально создаете другое имя, которое относится к одному и тому же функциональному объекту, как я уже делал в своем первом ответе, например.

hello() = "hi" 
goodbye() = "ciao" 

f = hello # f is a "function pointer" 
f() 

f = goodbye 
f() 

Вы можете легко разместить функции внутри других структур данных, например. словарь:

greeting = Dict("hello" => hello, "goodbye" => goodbye) 

f = greeting["hello"] 
f() 
Смежные вопросы