Introducing loopfusion: loop over any number of sequences of any single type.
After diving deep in the wonderful world of metaprogramming today, I'm happy to share the [loopfusion](https://github.com/numforge/loopfusion) package. For now you need to install it through `nimble install https://github.com/numforge/loopfusion`. This will give you 2 macros forEach and forEachIndexed that will allow you to iterate and operate over any number of sequences of any same type. Examples: import loopfusion let a = @[1, 2, 3] let b = @[11, 12, 13, 10] let c = @[10, 10, 10] forEach [x, y, z], [a, b, c]: echo (x + y) * z forEachIndexed j, [x, y, z], [a, b, c]: echo "index: " & $j & ", " & $((x + y) * z) 120 140 160 index: 0, 120 index: 1, 140 index: 2, 160 import loopfusion let a = @[false, true, false, true, false] let b = @[1, 2, 3, 4, 5] let c = @["a: ", "b: ", "c: ", "d: ", "e: "] var d: seq[int] = @[] forEachIndexed j, [x, y, z], [a, b, c]: if x: d.add $(y*y) else: d.add $y echo d @[0, 140, 320]
Re: Wrong copy of sequences?
`let` was designed to replicate parameter passing semantics so that a `template` can more easily do "evaluate once" for its parameters. Parameter passing also does not involve (deep) copies. Fixing/changing it will cause performance problems so it's not clear what to do.
Re: generic proc not instantiated depending on calling syntax
`x.y[z]` is `(x.y)[z]` and not `x.(y[z])`. There is nothing to disambiguate here, expression parsing produces a single consistent AST regardless of the involved symbols. There is no "partial call syntax with explicit generic types" in Nim's manual.
Re: How to turn thread spawn call into an async call
It's seems not perfect, but works, thank you.
Re: Wrong copy of sequences?
Yes, I think the last example is the most annoying one as, to solve it, we have to do a copy which is just something we don't want to do for obvious performance reasons. I have tried to change the parameter type from sequence to openarray with same result. And with an array instead of a sequence, we get the same behavior too. So, changing the semantic for sequences would not be enough, we would have to change the semantic for arrays, too, and kill the whole copy semantic of the language. Not the right way to go, I think. Maybe a clear distinction between mutable and immutable will indeed solve the issue. The difficulty is to find a balance between the increased complexity of the language and the performance.
Re: generic proc not instantiated depending on calling syntax
It's a known issue. It's hard to disambiguate "test".readMe[uint16]() with a bracket expression I suppose since at that time the compiler doesn't know if uint16 is a typedesc or an index I suppose. I think there is a RFC for that: [https://github.com/nim-lang/Nim/issues/3502](https://github.com/nim-lang/Nim/issues/3502)
Re: generic proc not instantiated depending on calling syntax
This works proc identity[T](name: T): T = result = name var n1 = "test".identity var n2 = 123.identity echo n1 echo n2
Re: cross-compiling nim using android-ndk 16.1
check this thread too [https://forum.nim-lang.org/t/3575](https://forum.nim-lang.org/t/3575)
generic proc not instantiated depending on calling syntax
The following program generates an error. Shouldn't it work? proc readMe[T](name: string): T = result = 123'u16 var num = "test".readMe[uint16]() # var num = readMe[uint16]("test") echo num Here are the error messages: t.nim(5, 17) template/generic instantiation from here t.nim(2, 13) Error: cannot instantiate: 'T' The workaround is to use the commented out line instead.
Re: Compiler won't scale (still)
Araq, maybe it would be more appropriate to have this as a warning instead of stopping compilation completely? Something like "Warning: Compiler has been through 1_000_000_000 iterations, compile time code might be in an infinite loop"
Re: Wrong copy of sequences?
For global variable example, I tried to modify the s and it cannot be compiled. Since s is considered immutable, so s is shared. However the member is mutable so it becomes like that. I think the only way to do it is to keep separation between mutable and immutable variable. That's why we can know for sure that immutable can always be shared while mutable always be copied (by default)
Re: Wrong copy of sequences?
Just thinking out loud: I image how difficult it would be to fix this one: var a = @[0, 1, 2, 3] proc p(s: seq[int]) = echo s # @[0, 1, 2, 3] a[^1] = 4 echo s # @[0, 1, 2, 4] p(a) Global alias analysis would be required or tons of not needed copies everywhere that will kill performance completely. And alias analysis is not perfect anyway, it gives answer `maybe` too often and resulting is unnecessary copy. It might be better to change the semantic of the language such that it shares always and copy happens only on explicit call to `copy()` so people know what to expect.