Hi all, new to Nim but I have really enjoyed using it thus far! I had a question about the benefits of using procs vs methods when defining methods (in the general sense) for various objects where there is inheritance. See below:

type
    BusinessCalendar* = ref object of RootObj
    TargetCalendar* = ref object of BusinessCalendar
    NullCalendar* = ref object of BusinessCalendar

proc isBusinessDay*(this: BusinessCalendar, dt: Time): bool = not(getLocalTime(dt).weekday in [dSat, dSun])

proc isBusinessDay*(this: NullCalendar, dt: Time): bool = false

proc advance*(this: BusinessCalendar, interval: TimeInterval, dt: Time): Time =
    var
        n = interval.days
        newdt = dt
    if n > 0:
        newdt += n.days
        while this.isBusinessDay(newdt) == false:
            newdt += 1.days
        n -= 1
    else:
        while n < 0:
            newdt -= 1.days
            while this.isBusinessDay(newdt) == false:
                newdt -= 1.days
            n += 1
    
    return newdt

proc adjust*(this: BusinessCalendar, dt: Time): Time =
    var newdt = dt
    while this.isBusinessDay(newdt) == false:
        newdt += 1.days
    
    return newdt

Is there a benefit to defining these as methods, or is using the static dispatch with the proc fine? Thanks in advance!

2017-08-11 13:41:38

To see the difference add this snippet to your code:

var calendar: BusinessCalendar
calendar = new TargetCalendar
echo calendar.isBusinessDay(getTime())  # prints `true` always, `BusinessCalendar.isBusinessDay` invoked
calendar = new NullCalendar
echo calendar.isBusinessDay(getTime())  # prints `true` with procedures and `false` with methods

Try it with BusinessCalendar declared as proc and as method.

Using proc you'll always call BusinessCalendar.isBusinessDay, because that's the type of the variable, and what to call is determined statically, that is at compilation time, exactly by the type of the variable.

Using methods what to call is determined at runtime, dynamically, by the actual type of object referenced by the variable. The first time it's TargetCalendar, which doesn't have its own method, so its base type (BusinessCalendar) method is called. The second time it's BusinessCalendar, which has its own method, which is called.

That is, if your objects are always assigned to variables of their own type and passed in arguments of their own type, you have no benefit of using methods (the same result and a little runtime overhead for methods). If actual type of the same variable may differ and at the same time should call its own, most specific, routine, then you need methods.

The same difference is between Delphi's and C++'s usual and virtual methods (maybe in some othe languages too), what info you can find for them is probably applicable here too.

2017-08-11 17:05:34