Is `macro` "a compressed part of code"?

According to this, I’m trying to use macro for inheritance as @xiaodai suggested.

However, I’ve not figured out how exactly macro works :frowning:

What I’m trying to do is basically “refering a struct’s fields from others”.
For this, here’s my example code:

abstract type AbstractABC end

mutable struct BaseABC <: AbstractABC
    a
end

mutable struct MyABC <: AbstractABC
    _abc
    b
end

macro inherit(ABC)
    ex = quote
        function Base.getproperty(abc::ABC, prop::Symbol)
            if prop in fieldnames(BaseABC) && !(prop in fieldnames(ABC))
                return getfield(abc._abc, prop)
            else
                return getfield(abc, prop)
            end
        end
    end
    return ex
end

@inherit(MyABC)

function test_all()
    baseabc = BaseABC(1)
    myabc = MyABC(baseabc, 2)
    println(myabc.a)  # should be "1"
end
test_all()

But it raises an error: UndefVarError: ABC not defined (at line 14).

Questions:

  1. Is macro a “compressed code”? I mean, macro probably runs at compile time as described here, then it seems “a function for automatic generation of codes” to me.
  2. If so, what should I correct to fulfill my purpose at the above code?

What I mean is something like this

@inherit mutable struct MyABC <: AbstractABC
   @embed _abc::BaseABC
    .... # other stuff
end

and it will generate the get property function as well.

u didn’t define a type called ABC do you mean MyABC?

I intended to use the @inherit for any structs, which is a subtype of AbstractABC.

I may wrongly be implementing macros (quite difficult to me :sweat: ).

Sorry for being bothering but can you give me an example code if u don’t mind?

I don’t understand what u r trying to do. Maybe u need to describe what u want. U only need macro if want the convenience

I did! I missed $.

What I was trying to do is to make a macro @inherit for any struct ABC (ABC <: AbstractABC such that @inherit ABC will make the struct ABC can refer any fields of BaseABC (BaseABC <: AbstractABC).

I would appreciate if you know a more convenient and Julian approach :slight_smile:

The corrected code:

abstract type AbstractABC end

mutable struct BaseABC <: AbstractABC
    a
end

mutable struct MyABC <: AbstractABC
    _abc
    b
end

macro inherit(ABC)
    ex = quote
        function Base.getproperty(abc::$ABC, prop::Symbol)
            if prop in fieldnames(BaseABC) && !(prop in fieldnames($ABC))
                return getfield(abc._abc, prop)
            else
                return getfield(abc, prop)
            end
        end
    end
    return ex
end

@inherit(MyABC)

function test_all()
    baseabc = BaseABC(1)
    myabc = MyABC(baseabc, 2)
    println(myabc.a)  # = 1
end
test_all()

The more julian approach is to simply not do this… generally, you will only define a small handful of types as subtypes of an abstract type. In that case you should just write out all of the fields explicitly (which also should be a small handful). If you have dozens of types or dozens of fields, that is code that needs refactoring.

abstract type AbstactX end

# an interface function to grab the :x field.
f(x::AbstractX) = x.x

struct X <: AbstractX
    x::Int
end

struct Y <: AbstractX
    x::Int
    y::Float64
end

struct Z <: AbstractX
    x::Int
    z::Float64
end

# etc.
3 Likes

Actually, I’m importing my Python codes into Julia codes as a first step :sweat:

Probably this would be a reason why I’m struggling with such non-Julian ways.

Unfortunately, although I’m doing my best to do that without Pythonic ways, I cannot find an alternative way to replace my codes in a whole Julian way :frowning:

Anyhow, thank you all :slight_smile:

1 Like

Yes, a 1-to-1 port from another language is hard. It is easier to think about the big picture of what the code is trying to accomplish and reimagine how to get to that goal from first principles. Usually you will find your result is clearer, faster, shorter, and simply better. For large code bases though, this process is hard and sometimes not worth it in the short term. If you want to DM me a link to your python code, maybe I can offer some directed advice.

6 Likes

@tomerarnon
I realised that such inheritance of structs would be unnecessary for my task (it was in my Python codes though).

So I tried to change it without inheritance, and it finally becomes much better to use in Julia.

Thanks :slight_smile:

3 Likes