Re: How to create adjacency list in Nim?

2020-03-02 Thread e
There are many ways to keep an adjacency list. The method I chose for a in a 
[quickie graph 
library](https://github.com/dcurrie/AdventOfCode/blob/master/Utils/dgraph.nim#L13-L14)
 was to use hash sets for in- and out- edges from a graph node.


Re: Share a paper: How to Print Floating-Point Numbers Accurately

2020-02-28 Thread e
This is a venerable paper. There is a new algorithm, [Ryū: fast float-to-string 
conversion](https://dl.acm.org/doi/10.1145/3296979.3192369) that is much 
faster. Here's some code: 
[https://github.com/ulfjack/ryu](https://github.com/ulfjack/ryu)


Re: Another Pythonish Compiled Language: Lobster

2020-01-23 Thread e
I found Lobster the same way as @ducktape (V discord), and decided to put it to 
the test with a difficult memory management challenge, a persistent balanced 
tree... difficult because there is no clear ownership model: structure is 
shared among all versions of the tree, and rebalancing makes link tracing 
non-trivial.

I happened to have an [implementation in 
Nim](https://github.com/dcurrie/nim-bbtree/blob/master/src/bbtree.nim) that I 
[ported to 
Lobster](https://github.com/dcurrie/lobster-bbtree/blob/master/bbtree.lobster).

The memory management worked well in both Nim (default gc) and Lobster.

The Lobster type inference/checker separates nillable and non-nillable versions 
of reference types, so several changes were needed to convince Lobster that 
references wouldn't be nil. The Lobster generic type inference is interesting 
to explore: typical Lobster code is very lightly annotated with types, if at 
all.


Re: Impossible situation trying to get minimal glfw example working±±±

2020-01-18 Thread e
Do you have glfw installed? If you use Homebrew, 


brew install glfw3


Run

may get you further.


Re: Naming conventions - need leading underscore

2020-01-17 Thread e
`multiplicative_inverse` and `multiplicatively_inversed` of course! 


Re: A path commonPrefix function

2020-01-06 Thread e
In `rangeAt` you have 


if xs[result.minAt] < xs[i]: result.minAt = i
if xs[result.minAt] > xs[i]: result.minAt = i


Run

whereas I suspect you meant to use `maxAt` in the second line. Does this affect 
your timing results?


Re: Advent of Nim 2019 megathread

2019-12-24 Thread e
Having decided to try learning a bit about Nim using AoC2019, I joined the 
[private leaderboard](https://adventofcode.com/2018/leaderboard/private), but 
never expected to be in the top 10 (I'm at 5 now, `dougcurrie`). So, I'll list 
my repo now in case anyone searching for Nim Advent of Code solutions in the 
future looks here. 
[https://github.com/dcurrie/AdventOfCode](https://github.com/dcurrie/AdventOfCode)


Re: Walking trees without recursive iterators

2019-12-18 Thread e
Does this test


if handle.par.len - 1 < handle.kidIx: false #kid@kidIx was deld post yield


Run

mean that deletion is only supported for the last kid (or all kid s)? E.g., if 
I don't delete kid 5, but then delete kid 4, isn't len still 4, so the test 
fails and we process kid 4's kids?


Re: Walking trees without recursive iterators

2019-12-17 Thread e
[Here](https://github.com/dcurrie/nim-bbtree/blob/master/src/bbtree.nim#L419-L446)
 is how I did it for a balanced binary tree without parent pointers, using an 
explicit stack as others have mentioned.


Re: Fastest way to check for int32 overflows

2019-12-09 Thread e
I keep this CMU SEI bookmark 
_
 as a reference for whenever I need to deal with overflow in C... it's probably 
useful for safe cross platform Nim coding, too.


Re: generic typevariable binding

2019-12-09 Thread e
Thanks, I created 
[https://github.com/nim-lang/Nim/issues/12863](https://forum.nim-lang.org/postActivity.xml#https-github-com-nim-lang-nim-issues-12863)


Re: generic typevariable binding

2019-12-08 Thread e
OK, I've boiled it down to this self-contained example:


import hashes, sets, tables
  
  type
DEdge*[K, V] = ref object
  fm*: DNode[K]
  to*: DNode[K]
  weight*: V

DNode*[K, V] = ref object
  key*: K

DGraph*[K, V] = object
  nodes: Table[K, DNode[K, V]]
  
  proc add_edge*[K, V](graph: var DGraph[K, V], fm: K, to: K, weight: V = 
V(1)): DEdge[K, V] =
var n1 = DNode[K, V](key: fm)
var n2 = DNode[K, V](key: to)
result = DEdge[K, V](fm: n1, to: n2, weight: weight)
  
  when defined(test1):

block:
  var w = DGraph[int,int]()
  let _ = w.add_edge(0, 1, 10)
  echo w

block:
  var g = DGraph[int,float]()
  let _ = g.add_edge(3,4,3.5)
  echo g
  
  when defined(test2):

block:
  var w = DGraph[int,int]()
  let _ = w.add_edge(0, 1, 10)
  echo w

block:
  var g = DGraph[uint,float]()
  let _ = g.add_edge(3u,4u,3.5)
  echo g


Run

Building with `-d:test2` works. Building with `-d:test1` yields: `Error: type 
mismatch: got  but expected 'DNode[system.int, 
system.int]'`

Should I create a github issue or am I misunderstanding something? 


Re: Recommended GUI library?

2019-12-08 Thread e
There's a list of [Curated 
Packages](https://github.com/nim-lang/Nim/wiki/Curated-Packages) that include a 
GUI section. I was pleased with how easy it is to get the cross-platform nimgui 
 working.


Re: Sublime Text 3 support

2019-12-04 Thread e
Yes, @Hendrik, Nimlime uses the nim that is installed and on your PATH.


Re: generic typevariable binding

2019-12-04 Thread e
Thanks @mratsim \-- I'll use your `weight = V(1)` suggestion.

I'm sorry you had to fill in missing bits... the failing code is 
[here](https://github.com/dcurrie/AdventOfCode/tree/master/Utils)

It fails if you uncomment the test case in `dijktra.nim` and try `nim c -r 
dijktra.nim`


generic typevariable binding

2019-12-04 Thread e
With a `type` that depends on two generic typevars, the type inference 
implementation seems to get stuck on a particular binding of the second typevar 
based on the first... is that expected?

Specifically, for these two sections:


var w = DGraph[int,int]()
let _ = w.add_edges(@[(0, 1, 10), (0, 4, 3), (1, 2, 2), (1, 4, 4)])

Run


var g = DGraph[int,float]()
let _ = g.add_edges(@[(3,4,3.5),(4,5,4.5)])

Run

the second one fails with `Error: type mismatch: got  but expected 'DNode[system.int, system.int]'`

If I reverse the sections, I get a similar failure with the `got` and 
`expected` types switched.

However, these work fine following either of the above:


var h = DGraph[uint,float]()
let _ = h.add_edges(@[(3u,4u,3.5),(4u,5u,4.5)])

Run


var k = DGraph[char,int]()
let _ = k.add_edges(@[('s','a',3),('s','c',2),('s','f',6)])

Run

The only thing that distinguishes the failure seems to the type taken on by the 
first typevar.

Help!?

Thanks.

\-- e

Below are more details:


type
  DEdge*[K, V] = ref object
fm*: DNode[K]
to*: DNode[K]
weight*: V
  
  DNode*[K, V] = ref object
key*: K
outedges: HashSet[DEdge[K, V]]
inedges:  HashSet[DEdge[K, V]]
priority*: V # for algorithms to sort upon
index*: int  # for algorithms to store sort position
  
  DGraph*[K, V] = object
# A directed graph of nodes and directed edges
nodes: Table[K, DNode[K, V]]

Run

and


proc add_edges*[K, V](graph: var DGraph[K, V], edges: seq[(K,K,V,)]): 
seq[DEdge[K, V]] =
  for (n1, n2, w) in edges:
result.add(add_edge(graph, n1, n2, w))

proc add_edge*[K, V](graph: var DGraph[K, V], fm: K, to: K, weight: V = 1): 
DEdge[K, V] =
  var n1 = graph.add_node(fm)
  var n2 = graph.add_node(to)
  result = DEdge[K, V](fm: n1, to: n2, weight: weight)
  result.fm.outedges.incl(result)
  result.to.inedges.incl(result)

proc add_node*[K, V](graph: var DGraph[K, V], key: K): DNode[K, V] =

Run


Re: Sublime Text 3 support

2019-12-04 Thread e
[Nimlime](https://github.com/Varriount/NimLime) works for me, at least for 
syntax(-error) highlighting and jump to definition. It has not been updated for 
about a year, but I've had no issues, though there are some listed on github. 
What trouble are you having?


Re: Manu v1.1 - Matrix Numeric package released!

2019-10-16 Thread e
The links in the docs are broken, e.g., 
[https://github.com/b3liever/manu//tree/devel/manu/qr.nim#L51](https://github.com/b3liever/manu//tree/devel/manu/qr.nim#L51)

Note that there is a `devel` in the path, whereas your repo has no `devel` 
branch. Perhaps it should be `master` instead.


Re: nim code coverage

2019-10-07 Thread e
coco, which uses lcov as above, is also broken with Nim 1.0.0

I added a ticket 
[https://github.com/nim-lang/Nim/issues/12376](https://forum.nim-lang.org/postActivity.xml#https-github-com-nim-lang-nim-issues-12376)


Re: generated_not_to_break_here breaks coco

2019-10-03 Thread e
Unfortunately that doesn't seem to work for me; I still get 


#line 99 "generated_not_to_break_here"


Run

In fact with `-d:release` I also get 


#line 189 "iterators.nim"


Run

as a relative path as well as the correct absolute path in the same file 


    #line 188 
"/Users/e/.choosenim/toolchains/nim-1.0.0/lib/system/iterators.nim"


Run

The absolute path works fine, but the relative path also messes up lcov. 


generated_not_to_break_here breaks coco

2019-10-03 Thread e
The Nim compiler is putting lines like this into the generated C code: 


#line 99 "generated_not_to_break_here"


Run

This is breaking `coco`, which uses `lcov` by causing it to try to process the 
file `generated_not_to_break_here`, which doesn't exist.

Is there a workaround? 


Re: Convert float to its corresponding bytes?

2019-01-26 Thread e
In C99 (ISO/IEC 9899:1999 6.5/7; the exact same wording is used in ISO/IEC 
9899:2011 §6.5/7)

> An object shall have its stored value accessed only by an lvalue expression 
> that has one of the following types ... a character type.

The meaning of "a character type" here includes unsigned char, which is also 
uint8. So, making some assumptions about the Nim code generator, both 
approaches are well defined in C.


Re: Convert float to its corresponding bytes?

2019-01-26 Thread e
Here's a little program demonstrating conversion functions:


import parseutils, os

func flt2arr (x: float64) : array[0..7, uint8] =
result = cast[array[0..7, uint8]](x)

func arr2flt (a: array[0..7, uint8]) : float64 =
result = cast[float64](a)

when isMainModule:
let params = commandLineParams()
var flt : float64
discard parseFloat(params[0], flt)
let ary = flt2arr(flt)
for u in ary:
echo(u)
let arr : array[0..7, uint8]
 = [ary[0]+1, ary[1], ary[2], ary[3], ary[4], ary[5], ary[6], ary[7]]
echo(arr2flt(arr))

Run


Re: generic instantiation with object inheritance

2019-01-23 Thread e
@Araq, The advantage I am trying to achieve is to minimize memory utilization. 
If I use variants to represent my nodes, I get a union from the Nim code 
generator:


struct tyObject_BBTreecolonObjectType__J7jcHxXTiq5WhuKk2uaAGQ {
  tyEnum_NodeKind_9bCibRYMAQfBZ6GB8aWzvUA kind;
  union {
struct { NI lkey; NI lval; };
struct { NI nkey; NI nval;
 tyObject_BBTreecolonObjectType__J7jcHxXTiq5WhuKk2uaAGQ* vleft;
 tyObject_BBTreecolonObjectType__J7jcHxXTiq5WhuKk2uaAGQ* vright;
 NI vsize;
};
  };
};

Run

I assume Nim will allocate the union for instances of my nodes, so there is no 
space savings. With inheritance and methods I was hoping that Nim would 
allocate smaller structures for leaf nodes. Is there a better way to do that? 
(I'm ok with "no," I just want to know if I've overlooked something.)


Re: generic instantiation with object inheritance

2019-01-22 Thread e
Thanks, @rayman22201 \-- I was just exploring, and knowing that Nim is broken 
with methods and generics is enough for me, though disappointing.


Re: generic instantiation with object inheritance

2019-01-20 Thread e
Working on minimal reproduction I triggered another bug that may be related. 
When my base method is discard, the second instantiation of my class fails to 
call the correct method size. I changed size to return a bogus value in the 
base case, which should never be called, and got

> Error: unhandled exception: cannot dispatch; dispatcher is nil 
> [NilAccessError]

See [gist](https://gist.github.com/dcurrie/e9e8955ccddb334130970b0b4a838bb8)


Re: generic instantiation with object inheritance

2019-01-18 Thread e
Yikes. It sure feels like I'm treading on thin ice...


Error: execution of an external compiler program 'clang -c  -w  
-I/Users/e/Dev/Nim/Nim/lib -I/Users/e/Dev/Nim/eNim/nim-bbtree/tests -o 
/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c.o 
/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c' failed with exit code: 1

/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c:6709:86: error: 
redefinition of 'left_2u7Q4oZNBna8dJLQnuQm6A'
N_LIB_PRIVATE 
N_NIMCALL(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*, 
left_2u7Q4oZNBna8dJLQnuQm6A)(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*
 n) {

 ^
/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c:5933:86: note: 
previous definition is here
N_LIB_PRIVATE 
N_NIMCALL(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*, 
left_2u7Q4oZNBna8dJLQnuQm6A)(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*
 n) {

 ^
/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c:6871:86: error: 
redefinition of 'right_2u7Q4oZNBna8dJLQnuQm6A_2'
N_LIB_PRIVATE 
N_NIMCALL(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*, 
right_2u7Q4oZNBna8dJLQnuQm6A_2)(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*
 n) {

 ^
/Users/e/.cache/nim/testbbtree_d/bbtree_testbbtree.c:6270:86: note: 
previous definition is here
N_LIB_PRIVATE 
N_NIMCALL(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*, 
right_2u7Q4oZNBna8dJLQnuQm6A_2)(tyObject_BBTreecolonObjectType__x9c9b9aUvIj9ao6qWVt1Yk55nw*
 n) {

   ^

Run


Re: generic instantiation with object inheritance

2019-01-18 Thread e
@rayman22201, thanks, that got me over that hump and much further along.

Now I'm running into cases where obj.proc (in my case, node.left for example) 
doesn't seem to work for method functions (in my case left) when there are 
arguments to the enclosing function with the same name as the method (in my 
case left). It worked before when left was a field of the object. I suspect I 
have hundreds of these to fix in my code... I'll report back when I've made all 
those changes to the argument names.


Re: generic instantiation with object inheritance

2019-01-18 Thread e
I'm on the verge of giving up on this; I'm now stuck on trying to create any 
non-nil tree. (Again, all this works with generics but not with object 
inheritance.) Here is the full reproducible example:


type
BBTree*[K,V] = ref object of RootObj # BBTree is a generic type with 
keys and values of types K, V
## `BBTree` is an opaque immutable type.
BBLeaf[K,V] = ref object of BBTree
vkey:   K   # the search key; must support the generic 
``cmp`` proc
vval:   V   # the data value associated with the key, 
and stored in a node
BBNode[K,V] = ref object of BBTree
vkey:   K   # the search key; must support the generic 
``cmp`` proc
vval:   V   # the data value associated with the key, 
and stored in a node
vleft:  BBTree[K,V] # left subtree; may be nil
vright: BBTree[K,V] # right subtree; may be nil
vsize:  int # the size of the (sub-)tree rooted in this 
node

method key[K,V](n: BBTree[K,V]): K {.base.} = discard
method val[K,V](n: BBTree[K,V]): V {.base.} = discard
method size[K,V](n: BBTree[K,V]): int {.base.} = discard
method left[K,V](n: BBTree[K,V]): BBTree[K,V] {.base.} = discard
method right[K,V](n: BBTree[K,V]): BBTree[K,V] {.base.} = discard

method key[K,V](n: BBLeaf[K,V]): K = n.vkey
method val[K,V](n: BBLeaf[K,V]): V = n.vval
method size[K,V](n: BBLeaf[K,V]): int = return 1
method left[K,V](n: BBLeaf[K,V]): BBTree[K,V] = discard
method right[K,V](n: BBLeaf[K,V]): BBTree[K,V] = discard

method key[K,V](n: BBNode[K,V]): K = n.vkey
method val[K,V](n: BBNode[K,V]): V = n.vval
method size[K,V](n: BBNode[K,V]):  int = return n.vsize
method left[K,V](n: BBNode[K,V]):  BBTree[K,V] = return n.vleft
method right[K,V](n: BBNode[K,V]):  BBTree[K,V] = return n.vright

func newLeaf[K,V](key: K, value: V): BBTree[K,V] =
# constructor for a leaf node
result = cast[BBTree[K,V]](BBLeaf[K,V](vkey: key, vval: value))

func nodeSize[K,V](n: BBTree[K,V]): int {.inline.} =
if n.isNil:
result = 0
else:
result = n.size

func newNode[K,V](left: BBTree[K,V], key: K, value: V, right: BBTree[K,V]): 
BBTree[K,V] =
# constructor for a new node
if left.isNil and right.isNil:
result = cast[BBTree[K,V]](BBLeaf[K,V](vkey: key, vval: value))
else:
let size = nodeSize(left) + 1 + nodeSize(right)
result = cast[BBTree[K,V]](BBNode[K,V](vleft: left, vright: right, 
vsize: size, vkey: key, vval: value))

# var root : BBTree[int,int] = nil # OK

# var root : BBTree[int,int] = newLeaf(1,-1) # fails bbtreen.nim(35, 38) 
Error: cannot instantiate: 'BBTree'

let empty : BBTree[int,int] = nil

var root : BBTree[int,int] = newNode(empty, 1, -1, empty) # fails 
bbtreen.nim(46, 42) Error: cannot instantiate: 'BBTree'

Run


Re: generic instantiation with object inheritance

2019-01-17 Thread e
Thank you @GULPF... this got me much further along.


Re: generic instantiation with object inheritance

2019-01-17 Thread e
@mratsim, that's interesting... why is there an extra dereference? My mental 
model is that the initial version has six contiguous fields (header, key, val, 
size, left, right), whereas the space saving version has either three (header, 
key, val) or six (header, key, val, size, left, right) depending on the 
subtype. Even if Nim needs an extra word of header space for discrimination of 
subtype, I don't see why it would need an additional reference.


Re: generic instantiation with object inheritance

2019-01-17 Thread e
@rayman22201, thanks. Yikes, what a hassle. I would have expected Nim to do 
that discrimination in its method dispatch.

Where is this kind of thing documented?


Re: generic instantiation with object inheritance

2019-01-16 Thread e
Casting to any of the subtypes of BBTree isn't safe because in the iteration of 
inorder the type of curr can be BBLeaf or BBNode2... isn't that the point of 
inheritance from a supertype?


generic instantiation with object inheritance

2019-01-16 Thread e
My persistent bounded balance tree library is working well. Now I want to 
optimize.

The tree type is


type
  BBTree*[K,V] = ref object of RootObj # BBTree is a generic type with keys 
and values of types K, V
  ## `BBTree` is an opaque immutable type.
  key:   K# the search key; must support the generic 
``cmp`` proc
  val:   V# the data value associated with the key, and 
stored in a node
  left:  BBTree[K,V]  # left subtree; may be nil
  right: BBTree[K,V]  # right subtree; may be nil
  size:  int  # the size of the (sub-)tree rooted in this 
node

Run

Since roughly half of all tree nodes are leaves with no need of left, right, or 
size fields, the first step is to introduce specialized leaf and internal node 
objects. I considered object variants to do this, but after digging into it 
determined that they are essentially C unions, taking the maximum size of any 
variant. (Document maintainers please note that clarifying this in the manual 
would be nice.) So, next try is object inheritance:


type
  BBTree*[K,V] = ref object of RootObj # BBTree is a generic type with keys 
and values of types K, V
  ## `BBTree` is an opaque immutable type.
  BBLeaf[K,V] = ref object of BBTree
  key:   K# the search key; must support the generic 
``cmp`` proc
  val:   V# the data value associated with the key, and 
stored in a node
  BBNode2[K,V] = ref object of BBLeaf
  left:  BBTree[K,V]  # left subtree; may be nil
  right: BBTree[K,V]  # right subtree; may be nil
  size:  int  # the size of the (sub-)tree rooted in this 
node

func size[K,V](n: BBLeaf[K,V]):  int = return 1
func left[K,V](n: BBLeaf[K,V]):  BBTree[K,V] = return nil
func right[K,V](n: BBLeaf[K,V]):  BBTree[K,V] = return nil

Run

Unfortunately, this leads to... Error: cannot instantiate: 'BBTree'

Using this test code:


iterator inorder*[K,V](root: BBTree[K,V]): (K,V) =
  ## Inorder traversal of the tree at `root`, i.e., from smallest to 
largest key
  # Since recursive iterators are not yet implemented, this uses an 
explicit stack
  var stack: seq[BBTree[K,V]] = @[]
  var curr = root
  while (not curr.isNil) or stack.len > 0:
  while (not curr.isNil):
  add(stack, curr) # push node before going left
  curr = curr.left
  # at the leftmost node; curr is nil
  curr = stack.pop()
  yield (curr.key, curr.val)
  curr = curr.right # now go right

# test

func isOrdered[K,V](root: BBTree[K,V], min: K): bool =
  var last = min
  for k,v in inorder(root):
  discard v
  if last == min:
  last = k
  elif cmp(last, k) < 0:
  discard # ok
  else:
  return false
  return true

var root : BBTree[int,int] = nil

assert(isOrdered(root, low(int)))

Run

I wondered if there is a problem with using common field names and proc names 
(e.g., left), so I tried this without success:


type
  BBTree*[K,V] = ref object of RootObj # BBTree is a generic type with keys 
and values of types K, V
  ## `BBTree` is an opaque immutable type.
  BBLeaf[K,V] = ref object of BBTree
  key:   K# the search key; must support the generic 
``cmp`` proc
  val:   V# the data value associated with the key, and 
stored in a node
  BBNode[K,V] = ref object of BBLeaf
  vleft:  BBTree[K,V]  # left subtree; may be nil
  vright: BBTree[K,V]  # right subtree; may be nil
  vsize:  int  # the size of the (sub-)tree rooted in this 
node

func size[K,V](n: BBLeaf[K,V]):  int = return 1
func left[K,V](n: BBLeaf[K,V]):  BBTree[K,V] = return nil
func right[K,V](n: BBLeaf[K,V]):  BBTree[K,V] = return nil

func size[K,V](n: BBNode[K,V]):  int = return n.vsize
func left[K,V](n: BBNode[K,V]):  BBTree[K,V] = return n.vleft
func right[K,V](n: BBNode[K,V]):  BBTree[K,V] = return n.vright

Run

What am I doing wrong? 


Re: Type instantiation for `==` func

2019-01-02 Thread e
So, digging deeper, the place where the generic instantiation is losing is


while curr != nil or stack.len > 0:

Run

So, the compiler can't infer a type for nil. It hadn't occurred to me to look 
for !=. If I replace that line with


while (not curr.isNil) or stack.len > 0:

Run

and do the same thing in several other places, the problem goes away. So, it 
does have to do the function's name, and the semantics of == and !=.

No compiler bug.

Thanks for your help.


Re: Type instantiation for `==` func

2019-01-01 Thread e
Having thought about this for a while, I am not advocating for a fix. I was 
hesitant to define the == func at all since it is comparing keys but not 
values, It is called set-equal? in MIT/Scheme wttree, not equal?. I only 
considered adding it to make the unit tests line up with other Nim set library 
unit tests. For that purpose, I've defined =?= instead .

It's reasonable for Nim to refuse to consider this func a true == if it can't 
unify U and V given a reasonable definition of equal, I just don't understand 
what language mechanism is preventing it.


Re: Type instantiation for `==` func

2019-01-01 Thread e
Sure, here are the relevant bits:


type
BBTree*[K,V] = ref object   # BBTree is a generic type with keys and 
values of types K, V
## `BBTree` is an opaque immutable type.
left:  BBTree[K,V]  # left subtree; may be nil
right: BBTree[K,V]  # right subtree; may be nil
size:  int  # the size of the (sub-)tree rooted in this 
node
key:   K# the search key; must suppprt the generic 
``cmp`` proc
val:   V# the data value associated with the key, 
and stored in a node

Run


func isSubset*[K,U,V](tree1: BBTree[K,U], tree2: BBTree[K,V]): bool =

Run

You can find the complete repo at 
[github](https://github.com/dcurrie/nim-bbtree)


Type instantiation for `==` func

2018-12-31 Thread e
My first Nim library, so newbie warning... The library is a persistent balanced 
tree data structure that can be used as a map or a set. It's mostly working and 
tested, but I ran into trouble trying to make a generic == to match the 
built-in Nim set equality operator. Since the comparison is on keys only (type 
K), the type of the values does not need to match (U and V here).

So, this works...


func `<=`*[K,U,V](s1: BBTree[K,U], s2: BBTree[K,V]): bool {.inline.} =
result = isSubset(s1, s2)

Run

but this gives **Error: cannot instantiate: 'V'**


func `==`*[K,U,V](s1: BBTree[K,U], s2: BBTree[K,V]): bool {.inline.} =
result = isSubset(s1, s2) and len(s1) == len(s2)

Run

Note that the type declarations are identical. Even if I make the bodies of the 
two functions identical, Nim still gives an instantiation error for the second 
one. Is there something special about == that is preventing this from working?