the last line echo y - (w*x) will not be compiled and the message is
R:\b.nim(26, 8) Error: type mismatch: got <seq[float], seq[float32]>
but expected one of:
proc `-`(x, y: seq[float | float32 | int]): seq[float32]
first type mismatch at position: 2
required type for y: seq[float or float32 or int]
but expression 'w * x' is of type: seq[float32]
21 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
expression: y - w * x
What is wrong with the code? And what is the proper way to define the type of function arguments which can be any number(number seq) of any number type(int, int32, int64, float, float32, ...)?
thanks
and the nim is
$ /c/tmp/Nim/bin/nim
Nim Compiler Version 1.3.5 [Windows: amd64]
Compiled at 2020-07-25
Copyright (c) 2006-2020 by Andreas Rumpf
the full code is
import math
proc `*`(n:float|int, y: seq[float|float32|int]): seq[float32] =
for i in 0 ..< len(y):
result.add float32(n * y[i])
return result
proc `-`(x, y: seq[float|float32|int]): seq[float32] =
for i in 0 ..< len(x):
result.add float32(x[i] - y[i])
return result
var
x = @[427, 459, 611, 593, 588]
y = @[-49.18, -22.21, 55.96, 117.37, 119.74]
w = 10
echo "x = ", x
echo "y = ", y
echo "\n"
echo w
echo w*x
echo y - (w*x)
Looks like a compiler bug to me, but when you use generics like this
`-`[A: float|float32|int, B: float|float32|int](x: seq[A], y: seq[B]): seq[float32] =
it works.but this falied
proc `-`[A: float|float32|int](x: seq[A], y: seq[A]): seq[float32] =
I was indeed a bit surprised that for
proc sqrsum(x, y: int | float): float =
we can now pass an int and a float variable with devil compiler. Its fine of course, see
we can now pass an int and a float variable with devil compiler.
devil compiler? Why not, but it’s a hell to use. :-)
Keep in mind that Nim is a statically typed language. Unlike dynamically typed languages (Python, Perl, Ruby, etc.), primitives like int and float don't have type information stored with them, so there's no way to have a seq[int|float] at runtime. Typeclasses are just a convenient syntax for generic types, which are strictly a compile-time concept. From the manual: "A type class is a special pseudo-type that can be used to match against types in the context of overload resolution or the is operator....Whilst the syntax of type classes appears to resemble that of ADTs/algebraic data types in ML-like languages, it should be understood that type classes are static constraints to be enforced at type instantiations. Type classes are not really types in themselves, but are instead a system of providing generic "checks" that ultimately resolve to some singular type. Type classes do not allow for runtime type dynamism, unlike object variants or methods."
rnatryour ints What are you expecting the type of @[myFloat] - 10 *@[myInt] to be? couldn't possibly work ... what would be the type of this expression? Not seq[int|float]--that would require either seqs to carry dynamic type information, or every element in the seq to carry individual type information.do
- it would require a conversion either from seq[int] to seq[float] or v.v.what would be the only work if a conversion from seq
- y = @[-49.18, -22.21, 55.96, 117.37, 119.74]
I have checked https://nim-lang.org/docs/lenientops.html, then a lazy-bone thought come into my mind: is there a way to write:
proc `-`(x, y: seq[float | float32 | int]): seq[float32]
but this ONE line is expanded to actually get 3*3 function definition lines, i.e.
proc `-`(x: seq[float], y: seq[float]): seq[float32]
proc `-`(x: seq[float], y: seq[float32]): seq[float32]
proc `-`(x: seq[float], y: seq[int]): seq[float32]
proc `-`(x: seq[float32], y: seq[float]): seq[float32]
proc `-`(x: seq[float32], y: seq[float32]): seq[float32]
proc `-`(x: seq[float32], y: seq[int]): seq[float32]
proc `-`(x: seq[int], y: seq[float]): seq[float32]
proc `-`(x: seq[int], y: seq[float32]): seq[float32]
proc `-`(x: seq[int], y: seq[int]): seq[float32]
Is it possible?As I indicate above you can write it like this with latest compiler:
proc `-`(x, y: seq[float] | seq[float32] | seq[int]): seq[float32] =
result.add(x[0].float32 + x[0].float32)
proc main =
var a: seq[int]
var b: seq[float]
a.add(1)
b.add(1)
var c = a - b
echo c[0]
main()
nim c t.nim
Hint: used config file '/home/salewski/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/salewski/Nim/config/config.nims' [Conf]
....CC: stdlib_formatfloat.nim
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: t.nim
Hint: [Link]
Hint: 21744 lines; 0.452s; 25.543MiB peakmem; Debug build; proj: /tmp/hhh/t.nim; out: /tmp/hhh/t [SuccessX]
salewski@nuc /tmp/hhh $ ./t
2.0
But can we really imagine use cases where we want to add elements of sequences with different types? At least mixing different float types we should avoid.
Welcome to the (second) wonderful world of distinct
proc `-`(x, y: distinct seq[float | float32 | int]): seq[float32] =
discard
Those are called the bind-many vs bind-once semantics
should work though I really really really do not like this: https://github.com/nim-lang/RFCs/issues/153