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!
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.