Suzhou-Tongyuan / ObjectOriented.jl

Conventional object-oriented programming in Julia without breaking Julia's core design ideas
MIT License
89 stars 6 forks source link

[Documentation Troubleshooting]: Implementing if-else block in @mk gives `invalid construction statement ` error #15

Open Shuvomoy opened 3 weeks ago

Shuvomoy commented 3 weeks ago

I am trying to implement the following Python class into equivalent Julia code using ObjectOriented.jl

## Python code
class MyType8:
    def __init__(self, a_input=30, b_input=50):
        # Clamping a_input within the range 0 to 100
        if a_input < 0:
            self.a = 0
        elif a_input > 100:
            self.a = 100
        else:
            self.a = a_input
            print("a_input is in the correct range")

        self.b = b_input

def myfun_type8(self):
    return self.a ** 2

def myfun2_type8(self, other):
    return self.a ** 2 + self.b ** 2 + other ** 2

# Creating instances
test1 = MyType8()

test2 = MyType8(a_input=200, b_input=50)

# Using the functions
result1 = myfun_type8(test2)
print("Result of myfun_type8(test2):", result1)

result2 = myfun2_type8(test2, 100)
print("Result of myfun2_type8(test2, 100):", result2)

It seems that ObjectOriented.jl does not accept if-else statement within an @mk block. For example the following code returns the error LoadError: invalid construction statement if a_input < 0:

## Julia code 
using ObjectOriented
@oodef mutable struct MyType8

    a
    b

    function new(; a_input = 30, b_input = 50)

        @mk begin
            if a_input < 0
                a = 0
            elseif a_input > 100
                a = 100
            else
                @info "a_input is in the correct range"
            end
            b = b_input
        end

    end

end
thautwarm commented 3 weeks ago

@mk is a shorthanded representation for something like a function call, where an LHS like a in a = 0 works like a keyword argument.

You may know the following 2 examples are not equivalent:

# case 1
a_input < 0  ? func(a = 1) : func(a = 100)

# case 2
func(a_input < 0 ? (a = 1) : (a=100))

The solution is to lift your if-else up:


@oodef mutable struct MyType8

    a  # I recommend you to use Generics or concrete types here
    b

    function new(; a_input = 30, b_input = 50)
        if a_input < 0
            a = 0
        elseif a_input > 100
            a = 100
        else
            @info "a_input is in the correct range"
            a = a_input
        end

        b = b_input;
        @mk begin
            a = a
            b = b
        end
    end
end

Writing the logics this way also helps me find out a potential bug (missing a when a_input in the correct range) in your example.

Shuvomoy commented 3 weeks ago

It makes sense, closing the issue. It may help to include similar examples in the documentation in the future. Thanks very much again!