# Implementing module, MethodError: objects of type Module are not callable

**URL:** https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202
**Category:** General Usage
**Created:** [October 19, 2023, 8:58pm UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202 "2023-10-19T20:58:43Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [October 19, 2023, 8:58pm UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/1 "2023-10-19T20:58:43Z")

</div>

I am trying to implement an R-like matrix where the columns/rows can be referred to by named indices.

```julia
using Revise
using Base

include("nm.jl")
using .NM

nm = NM.NamedMatrix(zeros(3, 2), ["row1", "row2", "row3"], ["col1", "col2"])

nm[["row1"], ["col1"]]

```

where nm.jl looks like

```julia
module NM

import Base

export NamedMatrix, getindex

mutable struct NamedMatrix
    matrix::Array{Float64,2}
    colnames::Vector{String}
    rownames::Vector{String}
end

function Base.getindex(x::NamedMatrix, i, j)
    if !(i == Base.(:))
        i = indexin(i, x.rownames)
    end
    if !(j == Base.(:))
        j = indexin(j, x.colnames)
    end
    NamedMatrix(x.matrix[i, j],
        x.rownames[i],        
        x.colnames[j])
end

end # module

```

However,

```julia
julia> nm[["row1"], ["col1"]]

```

gives this error:

> MethodError: objects of type Module are not callable

I am not sure why this is since I don’t recognize any naming conflicts with the Module name.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 19, 2023, 9:39pm UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/2 "2023-10-19T21:39:14Z")

</div>

I’ll go through some of the mistakes:

> [@hatmatrix](#):
>
> `import Base`

This isn’t necessary, don’t do it.

> [@hatmatrix](#):
>
> `export NamedMatrix, getindex`

Don’t `export getindex`, it’s not necessary and doesn’t do what you think it does.

> [@hatmatrix](#):
>
> `mutable struct NamedMatrix`

The `mutable` is almost surely not necessary (depending on what you want to do with the type).

> [@hatmatrix](#):
>
> ```julia
> colnames::Vector{String}
> rownames::Vector{String}
> 
> ```

The order of `colnames` and `rownames` isn’t consistent with the order you assume when you call the constructor. Swap them, for example.

> [@hatmatrix](#):
>
> `Base.(:)`

This is the reason for the “objects of type Module are not callable” error. Just do `:` instead.

> [@hatmatrix](#):
>
> ```julia
> NamedMatrix(x.matrix[i, j],
> x.rownames[i],        
> x.colnames[j])
> 
> ```

Just do `x.matrix[i, j]`, not sure what were you aiming for here.

Lastly, for performance reasons you probably want to keep the type of the variables `i` and `j` constant.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 20, 2023, 12:19am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/3 "2023-10-20T00:19:32Z")

</div>

`Base.(:)` is actually a broadcasted call. That means it’s interpreted as `Base` being the callable (it’s not, hence the error) and `:` being the iterable (it’s not) whose elements are put into a call in each iteration. Here’s an example of a broadcasted call (that works):

```julia
julia> typeof.( [1, 1.0, "one"] )
3-element Vector{DataType}:
 Int64
 Float64
 String

```

Incidentally, these are what you do instead of an accidental broadcasted call :

```julia
julia> :, Base.:(:), Base.Colon()
(Colon(), Colon(), Colon())

```

It’s analogous to these for the addition operator, except the parser let you omit the parentheses in this case:

```julia
julia> +, Base.:(+), Base.:+
(+, +, +)

```

I don’t expect this to be useful in practice, though. Since `Base` is imported by default and exports `:`, as pointed out already, you should just use `:`. ~~The parser also gets in the way of you trying to assign a `:` variable in different modules, so you’ll never need to do `NotBase.:(:)` to distinguish it from `Base.:(:)`.~~ I was wrong, you can assign it, you just need atypical parentheses so the parser doesn’t misinterpret it.

```julia
julia> module X (:) = 0 end;

julia> X.:(:)
0

```

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [October 20, 2023, 4:07am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/4 "2023-10-20T04:07:14Z")

</div>

Thanks a lot!

I had so many mistakes I didn’t know about or didn’t get to catching yet.

> Lastly, for performance reasons you probably want to keep the type of the variables `i` and `j` constant.

I realized now that I had to [write methods to include the Colon type](https://groups.google.com/g/julia-dev/c/ze38WWEbbIY/m/z5jiNw-_keoJ), otherwise it kept giving me an error when I would test for it. My current solution is

```julia
function Base.getindex(x::NamedMatrix, i::Union{Vector{<:Any}, Colon}, j::Union{Vector{<:Any}, Colon})
    if !isequal(i, :)
        i = indexin(i, x.rownames)
    end
    if !isequal(j, :)
        j = indexin(j, x.colnames)
    end
    NamedMatrix(x.matrix[i, j],
        x.rownames[i],        
        x.colnames[j])
end

```

And on this point,

> Just do `x.matrix[i, j]` , not sure what were you aiming for here.

I wanted the returned matrices to retain the index names, which is the (useful) behavior in R. R matrices are also mutable as well. In any case, I’m trying to port a library I wrote in R that inherits from its matrix class and this indexing behavior I find very useful.

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [October 20, 2023, 4:09am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/5 "2023-10-20T04:09:42Z")

</div>

Very informative addition, thanks.

The Module.:(Symbol) syntax would not have been intuitive but good to know more generally for non-base packages.

> The parser also gets in the way of you trying to assign a `:` variable in different modules

Sad that you cannot overload it though.

---

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [October 20, 2023, 4:40am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/6 "2023-10-20T04:40:30Z")

</div>

> [@hatmatrix](#):
>
> Sad that you cannot overload it though.

I was wrong earlier, you can assign a `:` variable. That’s not necessarily the same as _overloading_, though, it depends on if you explicitly used or imported `:` from Base. If you don’t, the `:` variable is totally separate from `Base.:(:)`. This is an example of overloading the `:` in `Base`:

```julia
julia> :
(::Colon) (generic function with 15 methods)

julia> Base.:(:)() = 0

julia> :
(::Colon) (generic function with 16 methods)

```

Here’s another in a fresh session:

```julia
julia> :
(::Colon) (generic function with 15 methods)

julia> import Base: :

julia> (:)() = 0
(::Colon) (generic function with 16 methods)

```

Don’t actually do these methods, though, you should have 2-3 arguments with custom types to properly use the `:` syntax.

---

<div class="post-metadata">

### Author: ![hatmatrix](https://avatars.discourse-cdn.com/v4/letter/h/5f8ce5/32.png) [@hatmatrix](https://discourse.julialang.org/u/hatmatrix)
#### Post date: [October 20, 2023, 5:31am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/7 "2023-10-20T05:31:55Z")

</div>

Ah, very well.

I don’t have plans to “overload” or add methods to this operator at the moment but was disappointed to think that there were limitations on this kind of flexibility in the language.

---

<div class="post-metadata">

### Author: ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)
#### Post date: [October 20, 2023, 7:19am UTC](https://discourse.julialang.org/t/implementing-module-methoderror-objects-of-type-module-are-not-callable/105202/8 "2023-10-20T07:19:03Z")

</div>

> [@hatmatrix](#):
>
> I wanted the returned matrices to retain the index names

Not sure why you’re trying to return a `NamedMatrix`, just return a `Tuple` instead.

```julia
module NamedMatrices

export NamedMatrix

struct NamedMatrix{T, I, J}
  matrix::Matrix{T}
  rownames::Vector{I}
  colnames::Vector{J}
end

# Safe construction. Some would use an inner constructor for this purpose.

"""
Public but not exported. Use for constructing named matrices.
"""
function construct(
  m::AbstractMatrix{T}, r::AbstractVector{I}, c::AbstractVector{J},
) where {T, I, J}
  (length(r) == first(size(m))) || error("row count mismatch")
  (length(c) == last(size(m))) || error("column count mismatch")
  NamedMatrix{T, I, J}(Matrix{T}(m), Vector{I}(r), Vector{J}(c))
end

# TODO: `helper` is not a good name

helper(::Colon, ::AbstractVector) = (:)

# The coercion ensures type stability.
helper(s, v::AbstractVector) = findfirst(==(s), v)::Int

const Arg = Union{T, Colon} where {T}

function Base.getindex(
  x::NamedMatrix{T, I, J}, s::Arg{I}, r::Arg{J},
) where {T, I, J}
  i = helper(s, x.rownames)
  j = helper(r, x.colnames)
  (x.matrix[i, j], s, r)
end

end

```

Usage example:

```julia-repl
julia> include("/tmp/NamedMatrices.jl")
Main.NamedMatrices

julia> using .NamedMatrices

julia> m = NamedMatrices.construct(rand(2, 3), ["firstRow", "secondRow"], [2//3, 1//3])
ERROR: column count mismatch
Stacktrace:
 [1] error(s::String)
   @ Base ./error.jl:35
 [2] construct(m::Matrix{Float64}, r::Vector{String}, c::Vector{Rational{Int64}})
   @ Main.NamedMatrices /tmp/NamedMatrices.jl:20
 [3] top-level scope
   @ REPL[3]:1

julia> m = NamedMatrices.construct(rand(2, 3), ["firstRow", "secondRow"], [3//3, 2//3, 1//3])
NamedMatrix{Float64, String, Rational{Int64}}([0.9164005697901872 0.2696022324777293 0.5365684417224075; 0.4401606748214111 0.7102419990453707 0.7351640896998047], ["firstRow", "secondRow"], Rational{Int64}[1, 2//3, 1//3])

julia> m["firstRow", 2//3]
(0.2696022324777293, "firstRow", 2//3)

```
