The solution is probably painfully simple to everyone but me :-(
Just trying to model Lisp's CAR, CDR functionality.
import lists
proc firstDbg(list: var SomeLinkedList) =
var node = list.head[]
node.next = nil
echo "first:", " type=", node.type, ' ', node.repr
# *** WHAT IS THE CORRECT SIGNATURE TO RETURN THE FIRST NODE OF THE PASSED IN LIST? ***
proc first(list: var SomeLinkedList): SomeLinkedNode =
result = list.head[]
result.next = nil
proc rest(list: SomeLinkedList): SomelinkedList =
result = list
result.head = result.head.next
var list = [1,2,3].toSinglyLinkedList
echo "list:", list
echo "rest:", list.rest
list.firstDbg # Just to show procedure body seems to generate the desired result
# Running with following *echo* line commented out generates:
# list:[1, 2, 3]
# rest:[2, 3]
# first: type=SinglyLinkedNodeObj[system.int] [next = nil,value = 1]
# echo "list:", list.first # *** WHAT I REALLY WANT ***
# *** UNCOMMENTING THE ABOVE LINE GENERATES THE FOLLOWING COMPILATION ERROR: ***
# test.nim(20, 19) template/generic instantiation of `first` from here
# test.nim(8, 39) Error: cannot instantiate 'SomeLinkedNode[T]' inside of type definition: 'first';
# Maybe generic arguments are missing?
proc first[T](list: var SomeLinkedList[T]): SomeLinkedNode[T]
also result = list.head[] must be result = list.head, you musnt dereference it otherwise you get the Obj version which isnt the return type you list
Thanks you very much. Yoy were correct on both counts. BTW: I also found another bug. My initial version accidently mutated in the source!
I finally ended up with:
proc first[T](list: var SomeLinkedList[T]): SomeLinkedNode[T] =
let node = list.head
result = node
Shouldn't this be instead:
proc first[T](list: SomeLinkedList[T]): SomeLinkedNode[T] =
result = list.head
But I don't understand the point of it anyway. Linked lists are a mostly obsolete data structure and not particularly convenient to work with either.
I disagree that linked lists are obsolete; they are fundamental to the history of computer science, are still widely used (e.g. the linux kernel is full of them), and are still useful in some niches (e.g. mutating a container while iterating over it)
car/cdr however, were assembly instructions for an obsolete architecture that never should have made it into a high-level language. (let alone the abominations cdaadr et al) but some folk value algorithmic purity over pragmatism.
Araq>Shouldn't this be ...
Proc first[T](list: SomeLinkedList[T]): SomeLinkedNode[T] =
result = list.head
Probaby... but I really didn't want the now extraneous next from the source. My implementation is less than ideal since it always allocates a new node...far from ideal in processing large linked lists (rare in real-life))
Araq> But I don't understand the point of it anyway. Linked lists are a mostly obsolete data structure and not particularly convenient to work with either.
I don't disagree... I never really used them in 40 years of professional programming. But now that I'm pushing 70... instead of doing sudoku and crossword puzzles to hold onto my limited cognitive function... I've been playing with Leetcode and the like. These are typical academic data-structure centered algorithms (nice little Kata sized problems).
Nice to review classic list based algorithms e.g.SICP to see the underpinnings for what we can so easily take for granted. Nothing like operating at a lower level to gain appreciation for higher level expressions :-)