Generics in Nim
import std/algorithm
# As an example of a generic function, `slicesIndex` takes
# a sequence of any comparable type and an element of that
# type and returns the index of the first occurrence of
# v in s, or -1 if not present.
proc slicesIndex[T](s: openArray[T], v: T): int =
for i, item in s:
if item == v:
return i
return -1
# As an example of a generic type, `List` is a
# singly-linked list with values of any type.
type
List[T] = ref object
head, tail: Element[T]
Element[T] = ref object
next: Element[T]
val: T
# We can define methods on generic types just like we
# do on regular types, but we have to keep the type
# parameters in place. The type is `List[T]`, not `List`.
proc push[T](lst: var List[T], v: T) =
let newElement = Element[T](val: v)
if lst.tail.isNil:
lst.head = newElement
lst.tail = lst.head
else:
lst.tail.next = newElement
lst.tail = lst.tail.next
# allElements returns all the List elements as a sequence.
proc allElements[T](lst: List[T]): seq[T] =
result = @[]
var e = lst.head
while not e.isNil:
result.add(e.val)
e = e.next
proc main() =
var s = @["foo", "bar", "zoo"]
# When invoking generic functions, we can often rely
# on type inference. Note that we don't have to
# specify the type for `T` when calling `slicesIndex` -
# the compiler infers it automatically.
echo "index of zoo: ", slicesIndex(s, "zoo")
# We could also specify the type explicitly if needed.
discard slicesIndex[string](s, "zoo")
var lst = List[int]()
lst.push(10)
lst.push(13)
lst.push(23)
echo "list: ", lst.allElements()
main()
This Nim code demonstrates the concept of generics, which is similar to the original Go example. Here are some key points about the translation:
Nim uses square brackets
[]
for generic type parameters, similar to Go.Instead of
~[]E
, Nim usesopenArray[T]
to represent a slice-like structure.Nim’s
proc
is equivalent to Go’sfunc
.Nim uses
var
for mutable parameters, similar to how Go uses pointers for mutability.Nim’s
ref object
is used to create a reference type, similar to Go’s struct pointers.Nim doesn’t require explicit type parameters when calling generic functions if they can be inferred.
The
main
function in Nim is not special; it’s just a regular procedure that we call at the end of the file.
To run this program, save it as generics.nim
and use the Nim compiler:
$ nim c -r generics.nim
index of zoo: 2
list: @[10, 13, 23]
This example demonstrates how Nim supports generics, allowing for type-safe, reusable code across different data types.