Author: | Kaushal Modi |
---|---|
License: | MIT |
Introduction
This module implements few Emacs-Lisp equivalent procs.
Source
Procs
proc car[T](s: openArray[T]): T
-
Return the first element of s.
If s has zero elements, throw an error. Unlike Emacs-Lisp, Nim cannot return a true "nil" value in this case.
Example:
doAssert @["abc", "def", "ghi"].car() == "abc" doAssert [1, 2, 3].car() == 1 try: discard seq[string](@[]).car() except AssertionError: echo "Illegal: 'car' was provided a zero-length seq/array."
proc cdr[T](s: openArray[T]): seq[T]
-
Return a sequence of all elements excluding the first element of s.
If s has one or less elements, an empty sequence of type T is returned.
Example:
doAssert @["abc", "def", "ghi"].cdr() == @["def", "ghi"] doAssert [1, 2, 3].cdr() == @[2, 3] doAssert [1].cdr() == seq[int](@[]) doAssert @["a"].cdr() == seq[string](@[]) doAssert seq[string](@[]).cdr() == seq[string](@[]) # zero length seq doAssert array[0, int]([]).cdr() == seq[int](@[]) # zero length array
proc assoc[T](alist: openArray[seq[T]]; key: T; testproc: proc (x, y: T): bool = equal): seq[T]
-
Return the first nested sequence whose first element matches with key using the testproc proc (which defaults to equal).
Input alist is an array or sequence of sequences of type seq[T].
The alist and key arguments are swapped compared to its Emacs-Lisp version so that we can conveniently do alist.assoc(key).
Example:
doAssert @[@["a", "b"], @["c", "d"]].assoc("a") == @["a", "b"] doAssert [@[1.11, 2.11, 3.11], @[4.11, 5.11, 6.11], @[4.11, 40.11, 400.11]].assoc(4.11) == @[4.11, 5.11, 6.11] # alist containing a zero-length seq doAssert [@[1, 2, 3], @[], @[4, 40, 400]].assoc(10) == seq[int](@[]) # zero length alist doAssert seq[seq[string]](@[]).assoc("a") == seq[string](@[])
proc delete[T](s: openArray[T]; el: T; testproc: proc (x, y: T): bool = equal): seq[ T]
-
Return a sequence containing all elements from s that do not match with el. The match is done using the testproc proc (which defaults to equal).
Example:
doAssert @[123, 456, 789, 123].delete(123) == @[456, 789] doAssert ["123", "456", "789", "123"].delete("456") == @["123", "789", "123"] doAssert seq[string](@[]).delete("a") == seq[string](@[])
proc mapconcat[T](s: openArray[T]; sep = " "; op: proc (x: T): string = dollar): string
-
Concatenate elements of s after applying op to each element. Separate each element using sep.
The signature of this proc differs from its equivalent mapconcat in Emacs,
- so that we can do s.mapconcat() in Nim.
- Also it is more common for a user to change the sep parameter than the op parameter, so move op to the last position.
Example:
doAssert @["abc", "def", "ghi"].mapconcat() == "abc def ghi" doAssert ["abc", "def", "ghi"].mapconcat() == "abc def ghi" doAssert [1, 2, 3].mapconcat() == "1 2 3" doAssert [1, 2, 3].mapconcat("\n", proc(x: int): string = "Ha: " & $x) == "Ha: 1\nHa: 2\nHa: 3" doAssert seq[string](@[]).mapconcat() == ""
proc member[T](el: T; s: openArray[T]): bool
-
Return true if el is an element in s. This proc is like find but with args in reverse order, and returns a bool instead.
Example:
doAssert "abc".member(@["abc", "def", "ghi"]) == true doAssert "abc".member(["abc", "def", "ghi"]) == true doAssert "a".member(["abc", "def", "ghi"]) == false doAssert 1.member([1, 2, 3]) == true doAssert 100.member([1, 2, 3]) == false doAssert "".member(seq[string](@[])) == false doAssert "a".member(seq[string](@[])) == false
proc isValid[T](x: T): bool
-
Return true if x represents something like a non-nil value in Emacs-Lisp.
Note: Compile with -d:debugIfLet to print if x is of unsupported type.
Macros
macro ifLet(letExpr: untyped; trueCond: untyped; falseCond: untyped = newEmptyNode()): untyped
-
Macro similar to Emacs Lisp's if-let* macro. Takes a set of assignments letExpr and checks if all of those are valid (in elisp, "validity" is checked by non-nil-ness) by calling isValid on the values being assigned. If all are valid, the body after do: will be evaluated, otherwise the body after else: is evaluate.
Note: Compile with -d:debugIfLet to see its resulting code.
ifLet: a = 5 b = a * 5 c = proc(a, b: int): int = a + b do: echo "Output is: ", c(a, b) else: echo "Either a or b had an invalid value."
This macro rewrites the above code to:
block: let a = 5 b = a * 5 c = proc (a, b: int): int = a + b if [isValid(a), isValid(b), isValid(c)].allIt(it): echo "Output is: ", c(a, b) else: echo "Either a or b had an invalid value."