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.