Step!() remains strangely unfound if buried inside another method

Hi. Can anyone please tell me why the call to step!(irg.odes) in the following code generates the error:
MethodError: no method matching step!(::DynamicalSystemsBase.CoupledODEs{true, ...?

Note that the call to reinit!(irg.odes) does not raise an error! :upside_down_face:

module Test
using DynamicalSystems

mutable struct IRGame
	odes::CoupledODEs
	function IRGame()
		new( CoupledODEs(
			function (du,u,p,t)
				du[1] = p[:alpha] * u[1]
				nothing
			end,
			[1.0],
			Dict(:alpha=>0.1)
		))
	end
end

function step!( irg::IRGame)
	reinit!( irg.odes)
	step!( irg.odes)
end

function demo()
	game = IRGame()
	step!(game)
end

end

You need to define this as function DynamicalSystems.step!(irg::IRGame) if you intend to add a new method to DynamicalSystems.step!, as otherwise you are declaring a completely unrelated step! function in your module that shadows the former function.

(Alternatively, call DynamicalSystems.step!(irg.odes) to explicitly call the step! function from the DynamicalSystems module.)

1 Like

Many thanks, @stevengi - that works beautifully. However, there is apparently some newby issue that Iโ€™m still not understanding: what is it that prevents multiple dispatch from distinguishing between my step! and DynamicalSystems.step! on the basis of their different argument types (IRGame and CoupledODEs)?

As Steven said you are shadowing the function - think of it as overwriting the definition, so step! is not related to DynamicalSystems.step! at all.

Hereโ€™s a simple example:

julia> struct A end

julia> sum(x::A) = 5
sum (generic function with 1 method)

julia> sum(A())
5

julia> sum([1,2,3])
ERROR: MethodError: no method matching sum(::Vector{Int64})
You may have intended to import Base.sum

As you see, the sum I created there has only 1 method, so there is nothing for multiple dispatch to do. For multiple dispatch to work Iโ€™d have import Base.sum and extend it, like here (new session):

julia> struct A end

julia> import Base.sum

julia> Base.sum(x::A) = 5

julia> sum(A())
5

julia> sum([1,2,3])
6
5 Likes

OK, I see. So the dispatcher only gets to do its work if the relevant functions are members of the same (or having common descent?) modules, is that right?

1 Like

Yes.