First issue is that BAST does not use references. This is so that searches proceed linearly through memory. Instead it uses a flat array that it cuts into sequentially doubling sized rows, representing the slots that a binary tree has.
Secondly, you just complicated my design even further with 'is left equal'. why not just 'go left' 'is this equal'? The implementation of the comparison could be different for all kinds of reasons. Number one reason that is already on my plan of action is where I have an arbitrary bit-width data, say 64 bits, but I want to sort one tree by the first 32 bits, and the same data feed into another tree at the same time that searches/sorts by the second 32 bits. This is the main reason for needing this flexibility. Mainly I want to stick to small blobs of memory, just numbers, mostly, but that at least includes 256 bit values. Much beyond that will destroy the advantage of this scheme, in that the tree will be too big in memory because of how large the probably 1/4 to half-filled node collection will generally be. On Monday, 23 April 2018 17:28:09 UTC+3, matthe...@gmail.com wrote: > > But I don't want to tie my users down to integers and floats. What if they >> want to sort strings? What if they want to sort complex numbers, matrixes, >> or what have you? > > > This is what the interface concept was made for. > > Why would the implementation of IsLeft be different if the BAST data is > organized another way? I think the abstraction you're expressed isn't > narrow enough. > > I don’t know the BAST details, but why not start here? > > type Node struct { > Element > Left *Node > Right *Node > } > > func (a Node) LeftEqual() bool { > if a.Left == nil { > return false > } > return a.Equal(a.Left.Element) > } > > type Element interface { > Equal(Element) bool > Null() bool > } > > Matt > > On Monday, April 23, 2018 at 8:55:14 AM UTC-5, Louki Sumirniy wrote: >> >> I did look at the Red/Black tree on Github and that was what got me >> started. But you need to understand exactly why those functions seem great >> in number. First of all, of course you could swap out 3 of those >> comparators for 1, and you probably don't even get why there is the 'empty' >> one. The datatype uses zero as a null value, as it is aimed at hashes and >> pretty much nothing hashes to zero (99.99999999% to understate it). >> >> In the code the caller would have to use, and this starts with my own >> code, so I am considering my own capacity to decode my code versus writing >> it in such a way that it is simple to understand. If I collapse those three >> functions into one, I either have to define a set of constants to put a >> human readable name on it - or, for a very small cost of maybe 10-15 bytes >> extra, human can read the code and know what it does and why it isn't >> incorrect. When you look further down to see what these functions are >> actually implemented with, you'll discover they are mostly one-liners. On >> the micro scale, it might seem making separate calls for these is a waste. >> But on the other side, if my caller code has to run a 3 level or longer >> if/then or switch/case, did I, as the programmer of the library, do my >> users (my fellow programmers) any favours? Nope! >> >> With this, the user can just say 'b.IsLeft(number, cursor)'. Sure, maybe >> there is no point in even having more than two conditions, since !IsLeft is >> the same as IsRight. But what if I wanted to descend the sort order. Then >> my code is riddled with '!IsRight' while I am trying to travel left. It's >> not good for the reader, and not good to read is hard to maintain, hard to >> maintain is expensive, and probably will be replaced by something else >> later. Reusability is very important for low level functions. It would be >> better for everyone if someone did the job right, first time, and for a >> long time afterwards, everyone can depend on it. >> >> And coming back full circle to how I came up with this, it was precisely >> by reading the cryptic and difficult to understand code of others, like >> that Red/Black tree. Computer programming is a heavy cognitive load task as >> it is. Arbitrary concepts of efficiency that don't take account for the >> cost of decoding the results of this theory tend to lead to reinventing the >> wheel, because the wheel was too cryptically constructed to simply modify >> it. >> >> </rant> >> >> The IsNull function is actually just a way of implementing x == 0. But I >> don't want to tie my users down to integers and floats. What if they want >> to sort strings? What if they want to sort complex numbers, matrixes, or >> what have you? I can't overload the equality operator, and even if I could, >> then there would be the issue of type inference, implicit casts, or the >> wordiness of explicit casts. Instead, the IsNull is already typed to the >> data you want to work with, it can have something other than zero as its >> null sentinel, or in other words, my slightly wordy interface means your >> sleek, svelte application that is easy to debug. >> >> On Monday, 23 April 2018 16:25:17 UTC+3, matthe...@gmail.com wrote: >>> >>> This is a code smell for me: >>> >>> type BAST interface { >>> AddRow() error >>> IsLeft(interface{}, Cursor) bool >>> IsRight(interface{}, Cursor) bool >>> IsEqual(interface{}, Cursor) bool >>> IsEmpty(Cursor) bool >>> … >>> >>> Interfaces should be small. This looks like a class definition which >>> isn’t a Go pattern. Also I would avoid interface{} if possible, and the >>> function types seem more complicated than necessary. I’m not convinced your >>> types/API are optimal. >>> >>> I still don’t exactly understand the goal, but this is my thinking about >>> the playground example: https://play.golang.org/p/KNdrYbebpuo >>> >>> Matt >>> >>> On Monday, April 23, 2018 at 3:46:03 AM UTC-5, Louki Sumirniy wrote: >>>> >>>> I spent two hours wrestling with this, but as you can see in this >>>> playground, the method I proposed totally works: >>>> https://play.golang.org/p/FMvisWS9tuP >>>> >>>> I propose that the type builtin when dealing with functions should have >>>> an extension made to it to add the method binding to the type signature so >>>> this workaround is not necessary. It would not break the spec, old code, >>>> or >>>> any of the goals that Go works towards. It would actually help with >>>> getting >>>> adoption by OOP programmers, in my view, because method overriding for >>>> this >>>> exact purpose of enabling the abstraction of backend type stuff (in my >>>> case >>>> it's just an array, but it could easily be a storage protocol or network >>>> protocol) would help immensely in implementing pluggable architectures. >>>> >>>> On Monday, 23 April 2018 08:23:24 UTC+3, Louki Sumirniy wrote: >>>>> >>>>> https://github.com/golang/go/issues/24996#issuecomment-383424588 >>>>> >>>>> It seems that (Type).FuncName in the assignment binds to the struct... >>>>> I am glad I found an answer so quickly because my hackish solution was >>>>> gonna be implemented today. >>>>> >>>>> On Monday, 23 April 2018 02:20:47 UTC+3, Louki Sumirniy wrote: >>>>>> >>>>>> You will see in the code I linked in the previous message that I >>>>>> already do have the interfaces in there. They can't be bound to the >>>>>> struct >>>>>> directly because I can't specify a function type that matches the >>>>>> signature, thus the use of a wrapper, and the interface types in the >>>>>> parameters. >>>>>> >>>>>> I just can't override them, and the great bulk of the code is not >>>>>> these small set of initialiser/allocator/comparator/getter/setter >>>>>> functions, so to have to search and replace through the whole thing, and >>>>>> maintain multiple nearly identical pieces of source code for the sake of >>>>>> 7 >>>>>> functions that are all very short, and differ between these versions, >>>>>> when >>>>>> everything else is the same... then I find a bug in one version, in the >>>>>> outer shell of the code and I have to merge every change of it into the >>>>>> other 5 versions... it's extremely cumbersome. >>>>>> >>>>>> The solution I have shown is just the first thing that looks to me >>>>>> like it would work. I have read tons of tutorials about composition and >>>>>> polymorphism and embedding in go, and in the end I pieced this together >>>>>> from several different things I learned. I tried several different >>>>>> things. >>>>>> It just makes absolutely no sense to have to go through and add a load >>>>>> of >>>>>> maintenance work to my code just so I can create, expand, read, write >>>>>> and >>>>>> compare values stored within the otherwise identical data structure. >>>>>> >>>>>> On Monday, 23 April 2018 01:44:43 UTC+3, matthe...@gmail.com wrote: >>>>>>> >>>>>>> Interface types are useful when the data structure is varied. Why >>>>>>> not an interface containing these varying functions as methods instead >>>>>>> of >>>>>>> function types? >>>>>>> >>>>>>> Matt >>>>>>> >>>>>>> On Sunday, April 22, 2018 at 5:20:12 PM UTC-5, Louki Sumirniy wrote: >>>>>>>> >>>>>>>> I essentially am trying to find an effective method in Go, >>>>>>>> preferably not too wordy, that lets me create an abstract data type, a >>>>>>>> struct, and a set of functions that bind to a different data type, and >>>>>>>> that >>>>>>>> I can write, preferably not in too much code, a change that allows the >>>>>>>> data >>>>>>>> type of the embedded data to be changed. It's basically kinda >>>>>>>> inheritance, >>>>>>>> but after much fiddling I found a hackish sorta way that isn't *too* >>>>>>>> boilerplate filled: >>>>>>>> >>>>>>>> type nullTester func(*Bast, uint32) bool >>>>>>>> >>>>>>>> type Bast struct { >>>>>>>> ... >>>>>>>> isNull nullTester >>>>>>>> ... >>>>>>>> } >>>>>>>> >>>>>>>> func isNull(b *Bast, d uint32) bool { >>>>>>>> return d == 0 >>>>>>>> } >>>>>>>> >>>>>>>> func NewBast() (b *Bast) { >>>>>>>> ... >>>>>>>> b.isNull = isNull >>>>>>>> ... >>>>>>>> } >>>>>>>> >>>>>>>> // IsNull - tests if a value in the tree is null >>>>>>>> func (b *Bast) IsNull(d uint32) bool { >>>>>>>> return b.isNull(b, d) >>>>>>>> } >>>>>>>> >>>>>>>> >>>>>>>> Now, bear in mind I haven't shown all of the code. But there is a >>>>>>>> slice array in the Bast struct, and I it is defined as an interface{} >>>>>>>> and >>>>>>>> isNull is one of a set of operators that have to be written to match >>>>>>>> the >>>>>>>> type used in the slice store, this might be a bad example because it >>>>>>>> doesn't actually act on the interface typed slice, but the point here >>>>>>>> is >>>>>>>> just this: >>>>>>>> >>>>>>>> It does not appear to be possible to make the type specification >>>>>>>> from the top line match the function signature of the type-bound >>>>>>>> function >>>>>>>> in the bottom of the code snippet. I haven't been able to find >>>>>>>> anything >>>>>>>> that shows that a func type can have a method binding. >>>>>>>> >>>>>>>> >>>>>>>> https://github.com/calibrae-project/bast/blob/master/pkg/bast/bast.go >>>>>>>> is where my WiP lives. This slightly hacky solution seems sound to me, >>>>>>>> I >>>>>>>> just don't like to be forced to use workarounds like this. If a type >>>>>>>> signature cannot be written that matches a method, yet I can do it >>>>>>>> this >>>>>>>> way, I don't see what purpose this serves as far as any kind of >>>>>>>> correctness >>>>>>>> and bug-resistance issues go. I would have to deal with a lot more >>>>>>>> potential bugs if I had to concretely implemennt this library for the >>>>>>>> sake >>>>>>>> of 1 slice and 7 functions out of a much larger library that >>>>>>>> conceptually >>>>>>>> is intended to only deal with comparable, mainly numerical values >>>>>>>> anyway. >>>>>>>> >>>>>>> -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.