-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] template constraint: allows overloading templates with untyped
; more powerful than concepts
#60
Comments
Yeah, whatever. So move your |
It feels like unnecessary complexity you can already do that today: template myMapImpl1() {.dirty.} =
discard
template myMapImpl2() {.dirty.} =
discard
template myMap[T](a:T, lambda: untyped) =
when isSomeProperty1(lambda, T):
myImpl1()
elif isSomeProperty2(lambda, T, Bar)
myImpl2()
else:
discard Edit: but yes that wouldn't help if we want a consistent |
In Nim, it's legal to say: template foo[T](x: T, y: SomeConcept[T]) ... which can be used to encode arbitrary inter-argument dependencies for well-typed arguments. Generic templates do have implementation issues right now though, so I'm not sure if the above works at the moment. What kind of constraint would you put on an |
are you sure?
that's not true under this proposal, see below examples based on
Many use cases:
# this checks that fun is a lambda
template map[T](s: T, fun:untyped) : auto when isLambda(fun) = ...
# more strict test: this checks that fun is a lambda that can be applied on `ElementType(s)`
template map[T](s: T, fun:untyped) : auto when isLambda(fun, ElementType(s)) = ...
# with:
template isLambda(fun:untyped, typedesc T): bool = compiles(lambdaEval(fun, T))
[1,2].map(a~>a*2) #ok: selects above map overload
# now, map can be overloaded (including in other modules!), eg:
template map[T, S](s: T, fun: proc (x: T)) : auto = ...
[1,2].map(a=>a*2) #ok: selects 2nd overload
# for mapIt afficionados (ie, with `it` shortform of lambdas); again, can be placed in a different module from other overloads!
template map[T](s: T, fun: untyped) : auto when isLambdaIt(fun, s) = ...
[1,2].map(it*2) #ok: selects 3nd overload
Note:
I know that (that's what I'm exploting in my universal toSeq PR nim-lang/Nim#8711); but that prevents having overloads in different modules, eg having a user defined imported
no, that cannot work: iterator myIter(a:int):auto = yield a
template toSeq2(s:Iterable)=discard # or even template toSeq2(s:typed)=discard
toSeq(myIter(3)) #works because toSeq accepts untyped (and this use case is used a lot)
toSeq2(myIter(3)) # Error: attempting to call undeclared routine: 'myIter' |
@timotheecour, I was trying to explain how the existing features of Nim fit into the picture, how the language can be extended in a logical way to reach your goals. Admittedly, I don't have a working solution for you now, only a possible alternative to what is being suggested here.
The https://nim-lang.org/docs/manual.html#term-rewriting-macros-parameter-constraints The reasoning why by So, if you want a new syntactic construct such as If you are after eliminating the indirect calls introduced by regular closures, Nim can also emulate C++-style functor objects through generic functions executed with types overloading the Finally, if you want to deal with the current problem of iterators not being properly typed (and the lack of support for higher-order iterators), let's write an RFC for that. I've been planning to write one myself. I do share the view that the best possible way to define |
|
/cc @zah
template foo[T](x: T, y: SomeConcept[T])
this has limitations that my RFC doesn't have, eg, arguments must be given in a specific order, see below: when defined(case1):
# ok
type SomeConcept[T] = concept a
var y:T
type(y[0]) is type(a)
proc foo[T](x: T, y: SomeConcept[T])=
echo (x,y)
foo([1], 2)
when defined(case2):
# Error: type mismatch
import timn/util/util_traits
type SomeConcept[T] = concept a
var y:T
type(y[0]) is type(a)
proc foo[T](x: SomeConcept[T], y: T) =
echo (x,y)
foo(2, [1]) in more complex cases, this workaround would become impossible. |
@timotheecour, do you have an example case where it's not possible to re-order the arguments to solve the problem? It seems to me that re-ordering won't be possible only if there are cyclic requirements between the types, but this sounds a bit ill-constructed at first glance. The problem can also be solved with a fixed-point binding process (or just by delaying the evaluation of the concepts), although this is not something I would like to add to the compiler. |
it's not always desirable to re-order elements, eg when overloading, or in case of UFCS where a variable makes more sense to be in 1st position, etc; and yes, cyclic requirements make this approach based on concepts impossible.
indeed, this would be lot more complicated than proposed template constraint |
This RFC is stale because it has been open for 1095 days with no activity. Contribute a fix or comment on the issue, or it will be closed in 30 days. |
in D, we can overload templates using template constraints:
in Nim, templates with
untyped
params can't have constraints attached to these untyped params so these can't be overloaded from these untyped params:This also leads to worse error messages and function documentation, since the type checking happens inside the instantiated
foo
, as opposed to before instantiation is attempted, via a template constraint.proposal: template constraint
suggested syntax:
comparison to concepts
=> doesn't seem possible in Nim
benefits
toSeq
overload messes up iterator visibility #7322=>
) Nim#8679) with type constraints and allow overloadinguntyped
params (early type checking); eg: would fix error message given here [1]isIterator
constraint, and restricting / overloading a template that takes anuntyped
argument representing aniterator
(eg use case:toSeq(walkPattern("..."))
; note thattoSeq(foo: iterator)
doesn't work for that: it requires untyped);openArray[T]
with template constraints, avoiding issues associated withopenArray
eg https://github.com/nim-lang/Nim/issues/9001 or converter gives inconsistent ambiguous call error with openarray Nim#10019)notes
discussion on syntax:
when
when
(or maybeconstraint
):links
[1] Confusing error message when calling toSeq using a non-iterator #7182
EDIT: implemented via nim-lang/Nim#12048 (need to check whether nim-lang/Nim#12048 100% covers this)
The text was updated successfully, but these errors were encountered: