Reputation: 3
when using Microsoft.SqlServer.TransactSql.ScriptDom for parsing, implementation of visitor usually looks like this:
open Microsoft.SqlServer.TransactSql.ScriptDom
let assembly _ =
let refs = ResizeArray()
refs, {
new TSqlFragmentVisitor() with
override this.Visit(s:CreateAssemblyStatement) = refs.Add(s)
}
each such visitor takes 6 LOC, while the only difference is typehint 'CreateAssemblyStatement'
so i tried this:
let visitor<'T> _ =
let refs = ResizeArray<'T>()
refs, {
new TSqlFragmentVisitor() with
override this.Visit(s:'T) = refs.Add(s)
}
let assemblyVisitor = visitor<CreateAssemblyStatement>
let executeVisitor = visitor<ExecuteStatement>
compiler complaints about non-restricted type:
error FS3213: The member 'Visit: 'T -> unit' matches multiple overloads of the same method.
Please restrict it to one of the following:
Visit: TSqlFragment -> unit
Visit: StatementList -> unit
...
adding type constraint did not help (TSqlFragment is base class):
let visitor<'T when 'T :> TSqlFragment> _ =
let refs = ResizeArray<'T>()
refs, {
new TSqlFragmentVisitor() with
override this.Visit(s:'T) = refs.Add(s)
}
so i believe this approach is just impossible, is there any other elegant way how to factor out that typehint?
Upvotes: 0
Views: 74
Reputation: 243041
Unfortunately, this is not going to be possible - and I cannot think of an elegant workaround.
The problem is that the Visit
methods of TSqlFramentVisitor
are not generic. This is an overloaded Visit
method that has a large number of overloads (1031 according to my VS tooltip!) Each of those methods is logically a different method (they happen to have the same name, but they could as well have all different names).
This means that there is no way to compile the generic visitor
function - because the compiler would need to decide, when compiling the visitor
function, which of the Visit
methods to override. Unfortunately, it cannot do this - because it can only decide this when it knows what the type of the method argument is (to choose one of the 1031 methods).
(Another issue is that, if someone defined a new class that inherits from TSqlFragment
, this might need to override a method that does not even exist!)
Upvotes: 3