-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[TODO] [easy] [typetraits] add ==
for type equality (different from is
!)
#8612
Conversation
lib/pure/typetraits.nim
Outdated
@@ -57,6 +57,16 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".} | |||
## This trait returns true iff the type ``t`` is safe to use for | |||
## `copyMem`:idx:. Other languages name a type like these `blob`:idx:. | |||
|
|||
proc sameType*(t1, t2: typedesc): bool = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I predict the same thing with name
will happen where people will ask for this to be renamed to ==
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i thought about it... not sure which is better; sameType is more searchable but ==
is more predictable; Note: there's also macros.sameType(Node,Node)
although obviously that one can't be named to ==
.
Overall ==
could be better ; should i go ahead and chage to ==
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. replace with ==
; which is nice because we get int != float
for free.
makes the language nice and uniform
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will quickly turn into compareTypes(a, b, flags)
anyway, ==
is for simple comparisons, type equality is anything but simple. In fact, I know few other examples where it gets as complex as it gets for types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well nothing wrong w having both ==
for simple comparison and, when needed, add compareTypes(a, b, flags)
to allow customizing what is meant by equality
PTAL |
==
for type equality
==
for type equality==
for type equality
==
for type equality==
for type equality
==
for type equality==
for type equality
How is this different to This passes: type T = int
doAssert T is int
doAssert int is T
doAssert int isnot float |
@dom96 type
C = concept x
x is int
echo int is C # true
echo C is int # false |
clarified documentation further to add what @GULPF said. |
This should be demonstrated in the runnable examples. |
lib/pure/typetraits.nim
Outdated
## Returns wheter ``t1``, ``t2`` are the same type; this is different | ||
## from ``t1 is t2`` since the latter supports concepts & inheritance. | ||
runnableExamples: | ||
type T=int |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style nitpick: space before and after =
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lib/pure/typetraits.nim
Outdated
type T=int | ||
doAssert T == int | ||
doAssert int == T | ||
doAssert: int != float |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please be consistent in your style, no need for this random :
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's needed to avoid #8300
otherwise you get: Error: invalid indentation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I doubt it. !=
is not an unary keyword operator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can try for yourself with git fetch origin pull/8634/head:pull_8634 && git checkout pull_8634
and remove this semicolon then nim doc ./lib/pure/typetraits.nim
to reproduce this error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This compiles:
import typetraits
type T = int
template `==`(x, y: typedesc): bool = (x is y) and (y is x)
doAssert T == int
doAssert int == T
doAssert int != float
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, this must've been fixed since that was reported
PTAL, all comments addressed |
/cc @dom96 friendly ping |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small things. I'm happy but I want @Araq to take a look too.
lib/pure/typetraits.nim
Outdated
@@ -57,6 +57,16 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".} | |||
## This trait returns true iff the type ``t`` is safe to use for | |||
## `copyMem`:idx:. Other languages name a type like these `blob`:idx:. | |||
|
|||
proc `==`*(t1, t2: typedesc): bool = | |||
## Returns wheter ``t1``, ``t2`` are the same type; this is different |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "whether".
I would also replace the comma with "and".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
lib/pure/typetraits.nim
Outdated
@@ -57,6 +57,16 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".} | |||
## This trait returns true iff the type ``t`` is safe to use for | |||
## `copyMem`:idx:. Other languages name a type like these `blob`:idx:. | |||
|
|||
proc `==`*(t1, t2: typedesc): bool = | |||
## Returns wheter ``t1``, ``t2`` are the same type; this is different | |||
## from ``t1 is t2`` since the latter supports concepts & inheritance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, is
supports concepts but not inheritance (that's of
AFAIK).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it does:
type A=object of RootObj
b1:int
type B=object of A
b2:int
echo A is B # false
echo B is A # true
I don't want it. People should use the
(2) is a never ending story and in the end you fail to produce a consistent system that people enjoy using after they got over the "I program in Nim for X days" phase. It's also after this phase when programmers become valuable contributors, generally speaking. We tried (2) for far too long, it's time to try (1). |
In my opinion having this function is a nice way to document this subtlety. Seeing the expression |
It doesn't come up often enough. Most of the time people would use it instead of |
3f0e797
to
714d1e7
Compare
I'm using both |
==
for type equality==
for type equality (different from is
!)
The tests in #8700 are passing now. |
Again, what are the use cases? |
eg:
import unittest
proc equals[T1,T2](a1:T1, a2:T2): bool=
# allows more efficient comparison; for example GC-free comparisons in tests,
# eg for procs returning a seq, we can compare against an array, which doesn't
# allocate
# replacing `T1==T2` by `T1 is T2` would produce different results in some cases, eg inheritance
when T1==T2 and isValueType(T1): # I implemented isValueType elsewhere; it's false if there are any nested references
# from https://github.com/nim-lang/Nim/issues/8436
return bitEquals(a1, a2)
elif compiles(a1.len) and compiles(a2.len):
if a1.len != a2.len: return false
for i in 0..<a1.len:
if not equals(a1[i], a2[i]): return false
return true
else:
return a1 == a2 |
714d1e7
to
bfa0b66
Compare
Well I was asking for concrete examples and you provided one where I have to ask: What's the point of the check? |
with with happy to provide full implementation for I also have an example where replacing |
Your check for And the reason why I don't like this feature is because this whole idea of builtin specialized typetraits does not scale. What should be done instead is to make use of |
I couldn't find isBlob in nim; so perhaps we actually mean the same thing? see below.
without seeing implementation it's hard to say it's wrong, so here is my implementation for given this implementation, why is it wrong? (besides the TODO of using a whitelist instead of i think it's a real example; it tries to handle as much cases as possible with bitEquals, reverting to manual behavior otherwise. it's not a workaround (of what?) {.reorder:on.}
proc defaultTemp[T]():T=
var a: T
return a
# TODO: map? etc
type RefType = ptr|pointer|ref|seq|string
proc isValueType(T:type RefType): bool = false
proc isValueType(T:type[tuple|object]): bool =
## returns whether T is a POD type
var a = defaultTemp[T]()
for i in fields(a):
if not isValueType(type(i)):
return false
return true
# proc isValueType(T:type array):bool = defaultTemp[T]()[0].type.isValueType
#or:
proc isValueType[N, T2](T:type[array[N, T2]]):bool = isValueType(T2)
# TODO: use whitelist instead (more robust)
proc isValueType(T:type[not(tuple|object|array|RefType)]):bool = true
proc isValueTypeTest()=
type A1=object
a:int
b:array[3, int]
c:type((1,2))
type A2=object
a:int
b:array[3, string]
var a:A1
var a2 = cast[pointer](a.addr)
require:
int.isValueType
float.isValueType
not string.isValueType
not seq[int].isValueType
(1,2).type.isValueType
not (1,"").type.isValueType
A1.isValueType
not A2.isValueType
not (ref A1).isValueType
not (ptr int).isValueType
a.type.isValueType
not a.addr.type.isValueType
not a2.type.isValueType
not pointer.isValueType
# make sure works at CT
static:
doAssert: not A2.isValueType |
Still not convinced. |
==
for type equality (different from is
!)==
for type equality (different from is
!)
No description provided.