Re: Generate doc comment from template?
You could do import macros macro setDocComment(a : static[string]) : untyped = result = nnkCommentStmt.newTree() result.strVal = a template foo(fn: untyped, doc: static[string]) = proc fn*(a: Foo) = setDocComment(doc) callfunc(fn, a) Run though it only immediately calls the macro setDoc if fn is a non generic proc For a template or generic proc you could instead do import macros macro foo(fn: untyped, doc: static[string]) = let docString = nnkCommentStmt.newTree() docString.strVal = doc result = quote do: proc `fn`*(a: Foo) = `docString` callfunc(`fn`, a) Run
Generate doc comment from template?
Is it possible to generate doc comments from templates? I have something like: template foo(fn: untyped, doc: string) = template fn*(a: Foo) = "## " & doc< I would like to inject doc comment here callfunc(fn, a) Run > that is instantiated like this: foo(bar, "Doc comment about bar") Run
Re: UncheckedArray conversion
I'm having a look at the moment, here are things that I find sketchy, note that I don't know the low-level VapourSynth API. 1\. You are not using `sampleType` or `bitsPerSample` in your example. > From what I understood, those format fields are supposed to tell you what > your `ptr UncheckedArray[byte]` really is, if you are like in the C++ case, > it's a type-erased float pointer so you should use the same. Note that > float32 vs int might be very relevant as floating point vector operations are > way more optimized than integers (for matrix multiplication the ratio is > between 10x to 100x depending on SSE4.1 AVX2 / AVX512 and fused multiply add > support) 2\. Profiling shows that row0 access is a bottleneck > 3\. Your iteration strategy seems problematic with repeated query to the API > to get the stride and pointer in vsframe.nim proc getPtr(frame:ptr VSFrameRef, plane:cint):uint = ## Retrieves an `uint` rather than the pointer in order to perform pointer arithmetic with it cast[uint]( API.getWritePtr(frame, plane) ) proc stride(frame:ptr VSFrameRef, plane:cint):uint = API.getStride( frame, plane ).uint #type # Row = ptr UncheckedArray[uint8] proc `[]`*(frame:ptr VSFrameRef, plane:cint, row:uint):ptr UncheckedArray[uint8] = let ini:uint = frame.getPtr(plane)# Don't use other thing here let stride:uint = frame.getStride( plane ) result = cast[ptr UncheckedArray[uint8]]( ini + row * stride ) #assert(result != nil) proc `[]`*(frame:ptr VSFrameRef, plane:cint, row:cint):ptr UncheckedArray[uint8] = let ini:uint = frame.getPtr(plane)# Don't use other thing here let stride:uint = frame.getStride( plane ) result = cast[ptr UncheckedArray[uint8]]( ini + row.uint * stride ) proc `[]`*(frame:ptr VSFrameRef, plane:cint ):Plane = let ini = frame.getPtr(plane) let stride = frame.stride(plane) return Plane(ini:ini,stride:stride) proc `[]`*(plane:Plane, row:cint):Row = #ptr UncheckedArray[uint8] = cast[ptr UncheckedArray[uint8]]( plane.ini + row.uint * plane.stride ) Run Instead I suggest you use a scheme like this, only get the plane/query the API once and use the plane object that holds the metadata. This way the compiler can do inlining and loop hoisting on all those accesses. The main issue with calling the VapourSynth API repeatedly is that all those function calls are just polluting your cache, requires the compiler to move the function parameter and result to and from the stack in an inner loop. import ../src/vapoursynth type Plane*[T: SomeNumber] = object # T depends on the frame format: # - sample_type (uint or float) # - bitsPerSample (8, 16, 32, 64) # The plane must be instantiated with # the proper uint8 ... 64, float32, float64 data: ptr UncheckedArray[T] rows: int cols: int rowStride: int func getPlane*(frame: ptr VSFrameRef, plane: int, T: typedesc[SomeInteger]): Plane[T] {.inline.} = ## Extract a plane result.data = cast[ptr UncheckedArray[T]](API.getWritePtr(frame, plane)) result.rows = API.getFrameHeight(frame, plane) result.cols = API.getFrameWidth(frame, plane) result.rowStride = API.getStride(frame, plane) template `[]`*[T](plane: Plane[T], row: int, col: int): T = plane.data[plane.row * plane.rowStride + plane.col] template `[]=`*[T](plane: Plane[T], row: int, col: int, val: T) = plane.data[plane.row * plane.rowStride + plane.col] = val Run Regarding iteration strategy, your scheme is doing 3 times more memory access than a basic scheme for each row and each column (total 9x). Instead you should iterate once per row/column but in-place accumulate with `dst[dstIdx] += src[srcIdx] * filter[filterIdx]` A starter point could be my basic convolution scheme in Laser [https://github.com/numforge/laser/blob/d1e6ae61/benchmarks/convolution/conv2d_direct_convolution.nim#L8-L73](https://github.com/numforge/laser/blob/d1e6ae61/benchmarks/convolution/conv2d_direct_convolution.nim#L8-L73) It's for batch of images with potentially different plane numbers (called channels) between in and out (for example RGB --> Grayscale) but the iteration should be faster than yours: Note that here I tracked the indices manually instead of using an intermediate `Plane` object but both methods should be the same with an optimizing compiler. proc conv2d_direct*[T]( oim: var Tensor[T], # Output images iim: Tensor[T], # Input images ishape: TensorShape,# Shape of a single image kernel: Tensor[T], # filter kernel kshape: KernelShape,# kernel shape (should be const) padding: Padding, # Padding (should be const) strides: Strides# Strides (should be
Re: Calling C function causes Sigsegv
[Here's](http://nimgen.genotrance.com/nimbass/bass.html#BASS_Init,cint,DWORD,DWORD,DWORD,pointer) what BASS_Init looks like in the wrapper I made some years ago. proc BASS_Init(device: cint; freq: DWORD; flags: DWORD; win: DWORD; dsguid: pointer): BOOL {...}{. stdcall, importc: "BASS_Init", dynlib: dynlibbass.} Run Bass will need stdcall on Windows. [https://github.com/genotrance/nimbass](https://github.com/genotrance/nimbass)
Re: Calling C function causes Sigsegv
I have wrapped plenty of C programs with Nim. My experience is that sig faults are caused by some thing simple ... like me not understanding the parameters. An equivalent C program should crash with a sig fault there too. I bet BASS_Init(-1, 44100, 0, 0, nil) would crash in C as well.
Re: UncheckedArray conversion
**C++ stuff** In order to test the C++ version: 1. The code can be downloaded from [here](https://github.com/IFeelBloated/test_c_filters). 2. I compiled it like: $ g++ -Wall -O3 -shared -fPIC -I. -o libfilter.so GaussBlur.cxx 3\. Create a VapourSynth python filter like test_filter.vpy: import vapoursynth as vs core = vs.get_core() core.std.LoadPlugin(path='./libfilter.so') core.std.SetMaxCPU('none') clip = core.std.BlankClip(format=vs.GRAYS, length=10, fpsnum=24000, fpsden=1001, keep=True) clip = core.testc.GaussBlur(clip) clip.set_output() Run 4\. Testing: $ vspipe test_filter.vpy /dev/null Output 10 frames in 29.53 seconds (3386.27 fps) So I am just getting 3386fps with the pure C++ version while I am getting 1200fps with the Nim version. I am not comparing apples to apples here: 1. The Nim version uses int32 while the C++ version uses float. 2. The Nim version is not using getFrameAsync, so it is not taking advantage of multithreading as discussed [here](https://github.com/vapoursynth/vapoursynth/issues/551#issuecomment-610473633).
Re: Nim programming book for kids
What is your definition of a "kid"? I don't think 99.9% of kids will want to read it. Back in the 80s I tried to learn BASIC using the TRS-80 Color Computer manuals, which were considered very high quality at the time. I didn't succeed, in part because I couldn't be bothered to read the text. There was too much of it. This text has even more. Last summer I had my older daughter (13) learn some Ada using a free online text I'd found. It was based on introducing ideas via a sequence of games. She did pretty well at it, but again, she didn't want to read it very much. She'd done some programming already with CSFirst, I think it's called, and that's a visual-oriented programming where you connect blocks. It did what she wanted: let her make animation with songs. Ada demanded too much of her just to get a simple text-based game. On the other hand, there seems to be disagreement between title and text. In your text you seem to walk back the title, and suggest that this is only an introduction to programming using Nim, a book for beginners. That's another matter, I guess, but the headline is a bit misleading then.
Calling C function causes Sigsegv
Hi, I'm trying to wrap a function of BASS sound library so I can learn how it works. My code is: #{. emit: """#include "bass.h" """ .} type dword {. importc: "DWORD" .} = uint32 type hwnd {. importc: "HWND" .} = uint32 type guid {. importc: "struct GUID" .}= object type cbool {. importc: "BOOL" .} = uint32 proc BASS_Init* (device: cint, frequency, flags: cuint, win: hwnd, guid: ptr guid): cbool {. importc, cdecl, header: "bass.h" .} echo $int(BASS_Init(-1, 44100, 0, 0, nil)) The function I'm wrapping is: BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); The reason I'm passing a nil pointer in the call to BASS_Init is because BASS will use the default value if it's null. Any hints?
Re: Nim programming book for kids
Really grateful for this effort.
Re: Having problems with concepts that won't finish compiling
Ahh, yes that is more convenient then passing all the fields manually! Thank you very much for the help :-D
Re: Having problems with concepts that won't finish compiling
Yes, either you use a template or if your object carries all the required data your handler can just have the type type Handler = proc(obj: MyObj) {.nimcall.} Run
Re: Nim programming book for kids
That's a very nice draft! It starts basic and soft but then it jumps to _high-level_ notions. I don't know if average children will understand. For instance, in the _What is a Programming Language_ section, you could explain what a compiler is compared with other way to run code, and what is the compilation process. Or before starting with syntax in _Part II: The basics_ , perhaps introduce what is the general structure of a Nim program, single or multiple sources. Last example, is explaining pointers in _References and Pointers_ a notion that must be introduced to child-programmers? I would wait until _Part V: Advanced topics_ section to write about pointers... A way to reach for children and beginners is to become quickly practical with examples or projects that they can try and extend on their computers. An example from Canada: [https://kidscodejeunesse.org/resources-for-educators](https://kidscodejeunesse.org/resources-for-educators). There must be other resources in other countries. Is there a way to report more precise critics directly in the text and help you?
Re: Nim programming book for kids
This looks awesome. I found a small issue while skiming the book: The example [here](http://ssalewski.de/nimprogramming.html#_input_and_output) don't need `import streams`, as `readLine` for `File` is in `io` and that one is imported by default.
Re: How do I pass Nim functions to C code as callbacks?
OK, here is an example. logic.c: typedef int (adder)(int, int); int run(adder fn, int a, int b) { return fn(a, b); } logic.nim: {. compile: "logic.c" .} type adder {. importc .} = proc(a, b: cint): cint proc run(fn: adder, a, b: cint): cint {. importc, cdecl, nodecl .} proc add(a, b: cint): cint {. cdecl .} = a+b var res=int(run(add, cint(100), cint(5125))) echo $res
Re: How do I pass Nim functions to C code as callbacks?
Do not call `tearDownForeignThreadGc`.
Re: How do I pass Nim functions to C code as callbacks?
I was just looking into this at this very moment and I am not sure if I use it well. I was reading the [Thread coordination](https://nim-lang.org/docs/backends.html#memory-management-thread-coordination) section and this [forum entry](https://forum.nim-lang.org/t/3965#24714). So I was implementing the following: proc callback( userData: pointer, f: ptr VSFrameRef, n: cint, a4: ptr VSNodeRef, errorMsg: cstring) {.cdecl.} = setupForeignThreadGc() #<- API.freeFrame( f ) tearDownForeignThreadGc()#<- proc NullAsync*(vsmap:ptr VSMap):int = let node = getFirstNode(vsmap) #API.freeMap(vsmap) let vinfo = API.getVideoInfo(node) # video info pointer let nframes = vinfo.numFrames for i in 0..
Re: Having problems with concepts that won't finish compiling
Interesting! If I understand you correctly, I should make a SplineType type with a handler field to hold the eval proc. And then newHermiteSpline() would return a SplineType with handler set to the Hermite's eval proc. Have I understood you correctly then? > How would you go about accessing the other variables of the Node in your > case? When you call the backward proc you would have to do something like > this right?: node.backward(node.gate, node.payload) Run Could that be shortened down to something that resembles node.backward()? A template could work I'd guess, something along the lines of: template eval*[T](spline: SplineType[T], x: float): untyped = spline.handler(spline.X, spline.coeffs, x) template eval*[T](spline: SplineType[T], x: openArray[float]): untyped = spline.handler_seq(spline.X, spline.coeffs, x) Run Could this work or did you have anything different in mind? :-)
Re: How do I pass Nim functions to C code as callbacks?
proc callback(arg: cint; arg2: cstring) {.cdecl.} = setupForeignThreadGc() # ... more code here toC(callback) Run
Re: UncheckedArray conversion
**Nim stuff** I have updated the [repository](https://github.com/mantielero/VapourSynth.nim). I have a local package.json with: [ { "name": "vapoursynth", "url": "https://github.com/mantielero/VapourSynth.nim;, "method": "git", "tags": [ "video", "vapoursynth" ], "description": "Video processing based on Vapoursynth", "license": "BSD" } ] With that you only need: nimble install vapoursynth The files to play with are [custom_filter.nim](https://github.com/mantielero/VapourSynth.nim/blob/master/test/custom_filter.nim) which makes use of [DrawFrame.nim](https://github.com/mantielero/VapourSynth.nim/blob/master/test/DrawFrame.nim). So you need these two files in the same folder and compile them like: nim c -d:release -d:danger custom_filter And in order to get the performance, just run it: $ ./custom_filter I will check how to do the same in C++.
Re: ggplotnim - pretty native plots for us
Ok, so I just merged the arraymancer backend PR, which includes the PR for version v0.2.0. v0.2.0 was mainly ridgeline plots and scale_*_reverse. Note that due to there is currently no recipe for a ridgeline plot. That will be added in the next few days. Also they are not as nice as they should be (essentially the top ridge doesn't change its height depending on the max values in the ridge if overflowing of ridges into one another is allowed). scale_*_reverse just allows to reverse scales as the name suggests. Aside from that a few smaller things were added (theme_void) and a few recipes that use geom_tile (annotated heatmap and plotting the periodic table). I'm not entirely happy with the state of version v0.3.0 though, since the formula mechanism introduces several breaking changes. Arguably reading formulas is now clearer (see the beginning of the README and especially the recipes, since they all have to be compliant with the new mechanism!), but it still requires code to be changed. I think the amount of breakage is probably not that large, since not that many people will have used formulas for things anyways yet. Also because the DF was discouraged before, since it was slow. Simple formulas e.g. f{"hwy"} remains unchanged anyways, same as f{5} to set some constant value to an aesthetic. But for these things formulas were previously only required for numbers and not referring to columns, since the aes proc took string | FormulaNode. Now also numbers are actually supported, so to set some constant value, you can just do aes(width = 0.5) instead of aes(width = f{0.5}). In any case, I wanted to get this PR off my chest, since it was way too large. I tried to avoid breaking changes as much as possibly by macro magic, but this issue: [https://github.com/nim-lang/Nim/issues/13913](https://github.com/nim-lang/Nim/issues/13913) was the nail in the coffin. So I just release it now. Feel free to open issues, because I broke your code. :)
Re: Nim programming book for kids
PDF Download would be cool. Awesome work!. :D
Nim programming book for kids
We had the discussion a few times in the last years -- if Nim is really a good start for kids and other people with absolutely no knowledge about CS. Nim is fine for bright kids, sure. But I hesitated generally to really recommend Nim for beginners, knowing that starting with the popular languages may be easier. On the other hand -- generally Nim would be a fine beginner languages, with fine teaching materials and always an experienced Nim dev sitting beside you. And when languages like C or Python are taught at school it seems to occur that that is sometimes done in a really bad and stupid fashion, and both of that languages are not perfect for teaching beginners. The Nim situation has indeed improved in the last years, Nim community has grown a bit, and the number of tutorials has grown a lot. Well, now there is one more. At least the first draft. Basically the result of maybe 10 days of work only. All was streamed directly from my head to the keyboard, so there may be some errors, due to the fine weather I have not done proofreading yet. But generally I am really satisfied with that start. Have no idea if I will work on it over the summer -- at least it is a start. [http://ssalewski.de/nimprogramming.html](http://ssalewski.de/nimprogramming.html)
How do I pass Nim functions to C code as callbacks?
H. I've looked around and I can't answer this. I want to be able to pass a Nim function / proc to C as a function pointer and get C to call it. I don't have a specific reason I want to do this, but I might need it soon. Thanks
Re: UncheckedArray conversion
If you have instructions to reproduce the benchmark in Nim and C++ I can help. I just need a repo to clone, the scripts to run and the dataset. I already have Vapoursynth working. Ideally you have a profiler like Intel Instruments or Apple VTune to dive into assembly. For example this is my approach in debugging performance issue: [https://github.com/nim-lang/Nim/issues/9514](https://github.com/nim-lang/Nim/issues/9514) For memory bottlenecks it's a bit different, I use the roofline model as mentioned in my convolution optimization resources: [https://github.com/numforge/laser/blob/master/research/convolution_optimisation_resources.md#computational-complexity](https://github.com/numforge/laser/blob/master/research/convolution_optimisation_resources.md#computational-complexity) For example I know that matrix multiplication and convolution can reach 90% of the peak CPU GFlop because their arithmetic intensity is high (i.e. you do over 10 operations (add/mul) per byte) so if you don't reach that perf it's because you are moving bytes to much instead of computing with them. The theoretical peak of your CPU is easy to compute: * single threaded: > `CpuGhz * VectorWidth * InstrCycle * FlopInstr` > for a CPU that supports AVX2 on float32 (so packing 8 float32) that can issue > 2 Fused-Multiply-Add per cycle at 3GHz we have `3 (GHz) * 8 (packed float32 in AVX) * 2 (FMA per cycle) * 2 (FMA = 1 add + 1 mul)` `= 96 GFlops` * multithreaded: Just multiply the single result by the number of cores. For example 10 cores would be 960 GFlops or 0.9 TFlops And then the usual way to benchmark numerical algorithm is, you know the number of operations required by your algorithm, you divide that by the time spent to do them and you have your actual flops. And you compare your actual Flops with the theoretical peak. If you only reach 20% of the peak, you have a memory bottleneck and probably need to repack before processing to optimize cache usage, if not you need to look into SIMD vectorization, prefetching, ... All of that is quite complex so what I can do is reach the naive C++ implementation performance. Going beyond is something that I want to do but it's time-consuming and I feel that it would be better to spend my time on an image processing compiler similar to what's discussed here: [https://github.com/mratsim/Arraymancer/issues/347#issuecomment-459351890](https://github.com/mratsim/Arraymancer/issues/347#issuecomment-459351890) and with a proof of concept here: * [https://github.com/numforge/laser/tree/master/laser/lux_compiler](https://github.com/numforge/laser/tree/master/laser/lux_compiler) * [https://github.com/numforge/laser/tree/master/laser/lux_compiler/core](https://github.com/numforge/laser/tree/master/laser/lux_compiler/core)
Re: Help with hash sets needed
thanks guys, make sense!
Re: Help with hash sets needed
Hello again ! A hash set is pretty much a hash table where the key and value types are the same. So, checking for the existence of an element in a hash set will do the following : * Check for the existence of the key based on its hash. * Compare the associated value with the element. This explains the results you had with that piece of code.
Re: Help with hash sets needed
Oh, and of course `a == b` must imply `hash(a) == hash(b)`.
Re: Help with hash sets needed
`hash` and `==` must agree. So, you need: proc `==`(a, b: ComponentPoint): bool = a.id == b.id Run
Help with hash sets needed
Hi everyone : ) type ComponentPoint* = object point: int id: int ## I want to calculate hash by only one variable proc hash(x: ComponentPoint): Hash = result = x.id var pp = ComponentPoint() pp.id = 1000 pp.point = 1000 var pp2 = ComponentPoint() pp2.id = 1000 pp2.point = 0 var hset= initHashSet[ComponentPoint](512) hset.incl(pp) # I suppose it must be true as the hashes are equal, but it's false assert pp2 in sss == true Run What's wrong with my code? ( Aside of primitive hash proc ) the thing is that is I set pp2.point to 1000 it gives the true. But Then I don't understand how things work under the hood. I thought that there is hash check and it must be valid.
Re: UncheckedArray conversion
You are probably right. For me is the first time doing this sort of stuff. But the feeling that I have is that even small modifications in the algorithm (avoiding conversions as much as possible, for example) has a significant impact. I think that the reason is that I am interating on 100_000 frames of 640x480 pixels. For instance I have just reached 1200fps just by replacing how the rows numbers are calculated. Changing this: template clamp(val:cint, max_val:cint):untyped = min( max(val, 0), max_val).uint . for row1 in 0..(vsapi->getReadPtr(frame, plane)); auto dstp = reinterpret_cast(vsapi->getWritePtr(dst, plane)); auto h = vsapi->getFrameHeight(frame, plane); auto w = vsapi->getFrameWidth(frame, plane); auto gauss = [&](auto y, auto x) { auto clamp = [&](auto val, auto bound) { return std::min(std::max(val, 0), bound - 1); }; auto above = srcp + clamp(y - 1, h) * w; auto current = srcp + y * w; auto below = srcp + clamp(y + 1, h) * w; auto conv = above[clamp(x - 1, w)] + above[x] * 2 + above[clamp(x + 1, w)] + current[clamp(x - 1, w)] * 2 + current[x] * 4 + current[clamp(x + 1, w)] * 2 + below[clamp(x - 1, w)] + below[x] * 2 + below[clamp(x + 1, w)]; return conv / 16; }; for (auto y = 0; y < h; y++) for (auto x = 0; x < w; x++) (dstp + y * w)[x] = gauss(y, x); Run When you mention memory bottleneck, what do you mean? Where should I look at? Thanks a lot
Re: UncheckedArray conversion
Type conversion from uint8 to uint32 (or uint64) is technically free because registers have a size of 32-bit or 64-bit. If anything it's less costly because at a low-level loading a 8-bit value requires movzb (mov to register and zero extend the byte) which has a slightly high latency than plain mov for uint32 and uint64. The issue in your convolutions is memory bottleneck not compute.
Re: Having problems with concepts that won't finish compiling
They are strongly discouraged. The most resilient way is probably to store your proc/method in a field and do the dynamic dispatch yourself, see `Backward` here: [https://github.com/mratsim/Arraymancer/blob/2c89da87/src/autograd/autograd_common.nim#L85-L96](https://github.com/mratsim/Arraymancer/blob/2c89da87/src/autograd/autograd_common.nim#L85-L96)
`{}` syntax
Some people don't read the RFCs often while everyone working with some new prog.lang _loves_ syntax debates. :-) So, to get broader exposure, here: [https://github.com/nim-lang/RFCs/issues/207](https://github.com/nim-lang/RFCs/issues/207)
Re: UncheckedArray conversion
This is part of a convolution filter. The result is in the same order of magnitude (uint8): let value:int32 = r0[col0].int32 + r0[col1].int32 * 2 + r0[col2].int32 + r1[col0].int32 * 2 + r1[col1].int32 * 4 + r1[col2].int32 * 2 + r2[col0].int32 + r2[col1].int32 * 2 + r2[col2].int32 w1[col1] = (value / 16.0).uint8 Run I am looking how to improve performance-wise without entering into SIMD stuff (that I have never used by the way). I think that all those type conversions are killing the performance that I should achieve.
Re: Is there non-broken serialization of complex types in nim?
my [package]([https://github.com/b3liever/eminim](https://github.com/b3liever/eminim)) mostly works
Re: Nim 1.2 is here
By the way, if Nim 1.2 requires a specific version of OpenSSL, this should be mentioned in [https://nim-lang.org/blog/2020/04/03/version-120-released.html](https://nim-lang.org/blog/2020/04/03/version-120-released.html)
Re: Is there non-broken serialization of complex types in nim?
Forgive me, I spotted where i messed up! I made table with `new_table` function, which produces `ref Table`, but deserialized it as `Table`
Re: Is there non-broken serialization of complex types in nim?
I was using marshal quite successfully before. I also use samson [https://github.com/GULPF/samson](https://github.com/GULPF/samson).
Is there non-broken serialization of complex types in nim?
Hi all. I resently asked a [question](https://forum.nim-lang.org/t/6153) about how can i serialize type like `table[A, Hash_set[A]]` in nim. I used standard marhal package (and still want to stick to standard library), but i can't deserialize it after serialization. When i try to, runtime crashes with /usr/lib/nim/pure/marshal.nim (333) to /usr/lib/nim/pure/marshal.nim (266) loadAny /usr/lib/nim/pure/marshal.nim (179) loadAny /usr/lib/nim/pure/parsejson.nim (522) raiseParseErr Error: unhandled exception: unknown file(1,1) Error: '{' expected for an object expected [JsonParsingError] Run But '{' is in place! This is how i try to deserialize it: let deserialized = read_file("serialized.json").to[:Table[A, Hash_set[A]] Run BTW it doesn't work even for simple types like strings or ints :(
Re: Another state of generating Android APK thread...
So here is my version of a [Maximally Factorized Sieve of Eratosthenes Benchmark as an Android app](https://github.com/GordonBGood/SieveofEratosthenesBenchmark) using an algorithm which is at least as fast as [Kim Walich's primesieve](https://github.com/kimwalisch/primesieve) on platforms on which they run in common up to the range of about 65 billion or so; it lacks the optimizations for more efficient sieving above this point in order to keep the code simpler and easier to understand. The required optimizations in order to extend the range to be the same are explained in the README file of the repo. This work was done to show that one doesn't need to write code in C/C++ in order to be fast as per [a Quora question on prime sieving](https://www.quora.com/Can-you-write-a-C-program-that-finds-all-prime-numbers-from-2-to-2-billion-in-under-1-second-on-an-average-500-PC), but the Quorum Moderators didn't accept my [answer](https://www.quora.com/Can-you-write-a-C-program-that-finds-all-prime-numbers-from-2-to-2-billion-in-under-1-second-on-an-average-500-PC/answer/W-Gordon-Goodsman), likely because it uses Nim rather than C++ and shows that it doesn't take a €500 PC to perform the task of sieving to two billion in under one second but that it can be done on the least expensive of currently available smartphones and not using C++. You can try this app by [downloading the zip file from here](https://github.com/GordonBGood/SieveofEratosthenesBenchmark/blob/master/app/release/SoEBenchmarkAndroid.zip), extracting the APK file, and side loading the APK file to an Android smartphone. The results should look something like the following: >
Re: UncheckedArray conversion
out of curiosity, isn't this prone to integer overflow or are you using value in fact as an uint32 ?
Re: Nim 1.2 is here
Isn't OpenSSL a system library? I am not sure how to update it without breaking a lot of things. I am using MacOS Sierra, this is probably why I am having trouble
template/generic instantiation of `initTable` from here - DateTime issue
Hi! I am trying to do the following: import tables, times type Person* = object name*: string birth_date_time*: DateTime proc newPerson(name: string, birth_date_time: DateTime): Person = return Person(name: name, birth_date_time: birth_date_time) var family = initTable[string, Person]() let papa = newPerson(name = "Udo", birth_date_time = initDateTime(1, mJan, 1980, 12, 0, 0, 0, utc())) family["Udo"] = papa let mama = newPerson(name = "Ida", birth_date_time = initDateTime(15, mApr, 1981, 12, 0, 0, 0, utc())) family["Ida"] = mama echo "Papa: " & family["Udo"].name & " - born: " & $family["Udo"].birth_date_time echo "Mama: " & family["Ida"].name & " - born: " & $family["Ida"].birth_date_time Run It works but y get `d:\Documents\Jobs\WTS\InvReporting\Prototype II\Research\DateTimeInTable\objects.nim(13, 23) template/generic instantiation of `initTable` from here C:\ProgramData\nim\lib\pure\collections\tables.nim(308, 12) Warning: Cannot prove that 'result' is initialized. This will become a compile time error in the future. [ProveInit] d:\Documents\Jobs\WTS\InvReporting\Prototype II\Research\DateTimeInTable\objects.nim(17, 7) template/generic instantiation of `[]=` from here C:\ProgramData\nim\lib\pure\collections\tableimpl.nim(49, 12) template/generic instantiation of `enlarge` from here C:\ProgramData\nim\lib\pure\collections\tables.nim(269, 10) Warning: Cannot prove that 'n' is initialized. This will become a compile time error in the future. [ProveInit] CC: objects.nim Hint: [Link] Hint: operation successful (42006 lines compiled; 1.295 sec total; 58.184MiB peakmem; Debug Build) [SuccessX] Hint: "d:\Documents\Jobs\WTS\InvReporting\Prototype II\Research\DateTimeInTable\objects.exe" [Exec] Papa: Udo - born: 1980-01-01T12:00:00Z Mama: Ida - born: 1981-04-15T12:00:00Z` This warning seems to be linked to the usage of DateTime as part of the object properties (It does not show up if e.g. using a string to represent the birth_date_time). Should I just ignore the warning, or better try a workaround? Background: I am building a solution that controls timing of data provision and time series type changes. Thus, a lot of DateTime type information flying around. Would rather prefer not messing around with strings all the time.