Hello,
Suppose this pseudo function:
proc fn[T](x: openarray[T]): ?
Here x can be a string, a seq or an array, right?
Is there any way to return a string when x is a string, a seq when x is a seq and an array when x is an array?
Thank you.
First, openArray stands for array or seq, not for string. Well I hope that is still the case, it was when I read the tutorial five years ago. I guess one can cast a seq[char] to string.
Note that Nim is statically typed, so the return type is well defined at compile time. But array type and seq type is very different, you may read that section already in my kids book, but it may contain some errors still.
So you can not have a single proc that can return array or seq. Basically you need two different procs.
We have "when" keyword in Nim as a compile time "if", and "auto" keyword as a possible return type. Both may help that we have to write only one proc, but the compiler will instantiate two for us. We have also or-types in Nim, we can write "int or float" in the parameter list and the compiler will instantiate one proc with int and one with float for us, and in the proc we can test with something like "when typeof(x) is float:"
But arrays are not a type but a typeclass, as arrays with same base type but different length are incompatible.
So I think there is no solution for you. Can you tell us what you want to archive?
How about
proc fn[T: openArray|array|seq](x: T): T
Thanks you for your replies.
So I think there is no solution for you. Can you tell us what you want to archive?
Yes, I've made a little XOR encrypter/decrypter for strings, seqs and arrays. It works perfectly but I was wondering if it was possible to do it using only one function instead of four.
# ----------------------------------------------------------------------------------------------------------------------
proc encrypterRaw*[T](data: var openarray[T], key: string) =
let dataCount = data.len() * sizeof(T)
let keyLen = key.len()
let dataPtr = getPtr(data)
if keyLen == 0:
return
var xorState: uint32 = 1
for i in 0 ..< dataCount:
xorState = xorState xor (xorState shl 13)
xorState = xorState xor (xorState shr 17)
xorState = xorState xor (xorState shl 5)
writePtr(dataPtr, readPtr(dataPtr, uint8, i) xor uint8(key[i mod keyLen]) xor uint8(xorState), uint8, i)
# ----------------------------------------------------------------------------------------------------------------------
proc encrypter*(str, key: string): string =
result = str
encrypterRaw(result, key)
# ----------------------------------------------------------------------------------------------------------------------
proc encrypter*[T](data: seq[T], key: string): seq[T] =
result = data
encrypterRaw(result, key)
# ----------------------------------------------------------------------------------------------------------------------
proc encrypter*[I, T](data: array[I, T], key: string): array[I, T] =
result = data
encrypterRaw(result, key)
Anyway, it does not matter, I'll leave it as it is.
Thank you ; )
@Hlaaftana
string is compatible with openarray[char]
Interesting. Is that guaranteed and stated in the manual?
@Javi
There may be indeed ways to simplify your source code by using auto keyword or by using typeof(param) as type for the result. I think I have used that somewhere, will try. But for each different array size that is used a own proc is instantiated.
No, string being an openarray does not seem to be mentioned in the manual.
That example might not work perhaps because of the excessive generic arguments? Try this:
proc encrypter*(data: array or seq or string, key: string): typeof(data) = ...
This uses something called implicit generics and is analogous to
proc encrypter*[T: array or seq or string](data: T, key: string): typeof(data) = ...
You can simplify the signature further with
proc encrypter*[T: array or seq or string](data: T, key: string): T = ...
I've made several tests and the suggestion of @Hlaaftana works very well, thanks!
proc encrypter*(data: string or seq or array, key: string): typeof(data) =