-1
echo 0.isNil

type mismatch: got < int literal(0)>
but expected one of: proc isNil[T: proc](x: T): bool
proc isNil[T](x: ptr T): bool
proc isNil(x: cstring): bool
proc isNil(x: pointer): bool
proc isNil(x: string): bool
proc isNil[T](x: seq[T]): bool
proc isNil[T](x: ref T): bool

How are we supposed to write generic code when we can't have expressions like 0.isNil ?

v.oddou
  • 6,476
  • 3
  • 32
  • 63
  • There's never any need for that expression in generic or any other code. `0` is no more equal to `nil` than `1` is. – Jim Balter Jun 15 '20 at 07:40
  • @JimBalter come on, a little bit of imagination. If I asked that, it's that I had a use case. `0` is not equal to `nil`, it's not what I said. I meant: `0.isNil` is false, and `1.isNil` is false too (because a literal exists). Duck typing can't be used if generic trait function like that are not universal. – v.oddou Jun 15 '20 at 09:56
  • I have more than enough imagination. The argument is completely bogus, and the question is poorly written pure hyperbole with no supporting evidence. As noted by the comment by uran, "Just like isEven and isOdd is defined for integers, why don't you complain that isEven is not defined for Files, because Files are not even, neither they are odd, right?" That's my final response. – Jim Balter Jun 15 '20 at 20:17
  • @JimBalter the philosophy for this motivation is in this article https://motsd1inge.wordpress.com/category/software/engineering/ – v.oddou Jun 16 '20 at 01:15

2 Answers2

5

You don't need to use isNil on types that can't be nil, that just doesn't make sense. When going generic (let's say you're implementing MyContainer[T]) you just introduce a new notion of emptiness (whatever that means to you) and use it in your generic code.

proc isEmptyElement[T](v: T): bool {.inline.} =
  when compiles(isNil(v)):
    isNil(v)
  elif T is SomeNumber:
    v == 0
  else:
    # Whatever else you mean by emptiness. Let's say is v the default value of T
    var d: T # Default value
    v == d

proc myContainerAdd[T](c: MyContainer[T], v: T) =
  if not v.isEmptyElement():
    # proceed

Note isEmptyElement can be simplified, it has more branches than actually needed just to demonstrate different approaches.

uran
  • 1,346
  • 10
  • 14
  • special cases are not special enough to break the rules & http://michaelfeathers.typepad.com/michael_feathers_blog/2013/11/unconditional-programming.html – v.oddou Apr 19 '18 at 09:33
  • You reimplemented `isNil` (by convenience wrapping it). That's a good proof that `isNil` is incomplete. And `valuetype.isNil` should return `false` it's easy to define and it makes perfect sense. What you introduce here is a notion covered by `Option[T]` https://nim-lang.org/docs/options.html which does not solve generic programming. – v.oddou Apr 19 '18 at 09:37
  • 6
    You can look at it from a different perspective. `isNil` is just a function defined for types that can be `nil`. You can define your own for your own type. Just like `isEven` and `isOdd` is defined for integers, why don't you complain that `isEven` is not defined for `File`s, because `File`s are not even, neither they are odd, right? If your generic algorithm needs to know whether a value (is nillable and is nil) that's a problem specific to just your algorithm, and you can solve it locally, with no extra abstractions leaking. – uran Apr 19 '18 at 09:53
2

Implement all the types!

proc isNil(x: int): string = "meme"

echo 0.isNil
Grzegorz Adam Hankiewicz
  • 7,349
  • 1
  • 36
  • 78
  • lol so basically we need to patch the language because it is incomplete. great – v.oddou Apr 18 '18 at 14:51
  • what do I do with float, double, literals, byte, char ..? what we want is not `int` but `value type` concept or something – v.oddou Apr 18 '18 at 14:53
  • 1
    @v.oddou you could write `proc isNil[T](x: T)` but if it is not done, maybe I would ask the Nim developers if there is a good reason for, and if not, make a pull request. – Grzegorz Adam Hankiewicz Apr 18 '18 at 16:14
  • yes the generic `T` sounds like the missing overload. now what needs to be proven, is that a better matching generic is always going to be selected for overload resolution. (ref T..) – v.oddou Apr 19 '18 at 09:42