Task: VList

C: #include <stdio.h>
#include <stdlib.h>

typedef struct sublist{
	struct sublist* next;
	int *buf;
} sublist_t;

sublist_t* sublist_new(size_t s)
{
	sublist_t* sub = malloc(sizeof(sublist_t) + sizeof(int) * s);
	sub->buf = (int*)(sub + 1);
	sub->next = 0;
	return sub;
}

typedef struct vlist_t {
	sublist_t* head;
	size_t last_size, ofs;
} vlist_t, *vlist;

vlist v_new()
{
	vlist v = malloc(sizeof(vlist_t));
	v->head = sublist_new(1);
	v->last_size = 1;
	v->ofs = 0;
	return v;
}

void v_del(vlist v)
{
	sublist_t *s;
	while (v->head) {
		s = v->head->next;
		free(v->head);
		v->head = s;
	}
	free(v);
}

inline size_t v_size(vlist v)
{
	return v->last_size * 2 - v->ofs - 2;
}

int* v_addr(vlist v, size_t idx)
{
	sublist_t *s = v->head;
	size_t top = v->last_size, i = idx + v->ofs;

	if (i + 2 >= (top << 1)) {
		fprintf(stderr, "!: idx %d out of range\n", (int)idx);
		abort();
	}
	while (s && i >= top) {
		s = s->next, i ^= top;
		top >>= 1;
	}
	return s->buf + i;
}

inline int v_elem(vlist v, size_t idx)
{
	return *v_addr(v, idx);
}

int* v_unshift(vlist v, int x)
{
	sublist_t* s;
	int *p;

	if (!v->ofs) {
		if (!(s = sublist_new(v->last_size << 1))) {
			fprintf(stderr, "?: alloc failure\n");
			return 0;
		}
		v->ofs = (v->last_size <<= 1);
		s->next = v->head;
		v->head = s;
	}
	*(p = v->head->buf + --v->ofs) = x;
	return p;
}

int v_shift(vlist v)
{
	sublist_t* s;
	int x;

	if (v->last_size == 1 && v->ofs == 1) {
		fprintf(stderr, "!: empty list\n");
		abort();
	}
	x = v->head->buf[v->ofs++];

	if (v->ofs == v->last_size) {
		v->ofs = 0;
		if (v->last_size > 1) {
			s = v->head, v->head = s->next;
			v->last_size >>= 1;
			free(s);
		}
	}
	return x;
}

int main()
{
	int i;

	vlist v = v_new();
	for (i = 0; i < 10; i++) v_unshift(v, i);

	printf("size: %d\n", v_size(v));
	for (i = 0; i < 10; i++) printf("v[%d] = %d\n", i, v_elem(v, i));
	for (i = 0; i < 10; i++) printf("shift: %d\n", v_shift(v));

	 

	v_del(v);
	return 0;
}




Go: package main

import "fmt" 

type vList struct {
    base   *vSeg
    offset int
}

type vSeg struct {
    next *vSeg
    ele  []vEle
}


type vEle string
    

func (v vList) index(i int) (r vEle) {
    if i >= 0 { 
        i += v.offset
        for sg := v.base; sg != nil; sg = sg.next {
            if i < len(sg.ele) {
                return sg.ele[i]
            }
            i -= len(sg.ele)
        }
    }
    
    panic("index out of range")
}


func (v vList) cons(a vEle) vList {
    if v.base == nil {
        return vList{base: &vSeg{ele: []vEle{a}}}
    }
    if v.offset == 0 {
        l2 := len(v.base.ele) * 2 
        ele := make([]vEle, l2)
        ele[l2-1] = a
        return vList{&vSeg{v.base, ele}, l2 - 1}
    }
    v.offset--
    v.base.ele[v.offset] = a
    return v
}   



func (v vList) cdr() vList {
    if v.base == nil {
        
        panic("cdr on empty vList")
    }
    v.offset++
    if v.offset < len(v.base.ele) {
        return v
    }
    return vList{v.base.next, 0}
}


func (v vList) length() int {
    if v.base == nil {
        return 0
    }
    return len(v.base.ele)*2 - v.offset - 1
}


func (v vList) String() string {
    if v.base == nil {
        return "[]"
    }
    r := fmt.Sprintf("[%v", v.base.ele[v.offset])
    for sg, sl := v.base, v.base.ele[v.offset+1:]; ; {
        for _, e := range sl {
            r = fmt.Sprintf("%s %v", r, e)
        }
        sg = sg.next
        if sg == nil {
            break
        }
        sl = sg.ele
    }
    return r + "]"
}


func (v vList) printStructure() {
    fmt.Println("offset:", v.offset)
    for sg := v.base; sg != nil; sg = sg.next {
        fmt.Printf("  %q\n", sg.ele) 
    }
    fmt.Println()
}


func main() {
    var v vList
    fmt.Println("zero value for type.  empty vList:", v)
    v.printStructure()

    for a := '6'; a >= '1'; a-- {
        v = v.cons(vEle(a))
    }
    fmt.Println("demonstrate cons. 6 elements added:", v)
    v.printStructure()
    
    v = v.cdr()
    fmt.Println("demonstrate cdr. 1 element removed:", v)
    v.printStructure()

    fmt.Println("demonstrate length. length =", v.length())
    fmt.Println()

    fmt.Println("demonstrate element access. v[3] =", v.index(3))
    fmt.Println()

    v = v.cdr().cdr()
    fmt.Println("show cdr releasing segment. 2 elements removed:", v)
    v.printStructure()
}