rerunning CI works for github actions, sr.ht, but not azure pipelines
I'd like to be able to re-run CI just for what needs to be re-run without having to re-run everything to save CI cycles. this works fine for sr.ht (if you have an account), and for github actions (when it fails, IIRC you can rerun at least if project member), but somehow not for azure pipelines. Anything can be done? (related: [https://github.com/nim-lang/Nim/pull/13556](https://github.com/nim-lang/Nim/pull/13556) which would enable [nimDocOnly] in commit msg ; but needs to be updated to reflect how CI is split amongst github actions and azure)
Re: How to instantiate `ptr object`
One of the things that intrigued me about Nim was it's object system, you could create value, reference and pointer types with/without inheritance. As I understand it, an important distinction between ptr and ref classes is that ref classes are managed by the garbage collector while ptr classes have to be manually allocated and deallocated. In this case for me that _is_ the distinction between both of them, I see inheritance from a ptr class as the same as inheritance from a ref class and polymorphism in the same way: type: Animal = ptr object of RootObj Cat = ptr object of Animal var x: Animal = create(Cat) Run But I also want to be able to dispatch against Cat (x) at runtime, so send it as a parameter in a function marked with Animal but within that function call the cat method and allow the right method to be dispatched. In exactly the same way as in my kernel function: proc calculateKernelMatrix*(K: AbstractKernel, data: Matrix[F]): Matrix[F] = let n = int64(ncol(data)); var mat = Matrix[F](data: newSeq[F](n*n), dim: @[n, n]); for j in 0..
Re: Idea why this does not compile?
> need to define your destructor earlier Yes, my initial guess was indeed that, as it was done in that way in the earlier gintro code. But I became unsure if it would work really fine also that way. And it remains strange, as my fnew template should fully hide the use of the finalizer when we compile with --gc:arc. So I assume that both branches of the when construct are processed by the compiler and that confuses the compiler? In the same way as discarded code is always syntax checked? Unfortunately ordering the code is not that easy, as it is autogenerated from the gobject-introspection database, and for latest gtk 3.98.3 which will become 4.0 there are some serious changes. I can not just put the =destroy just after the type declaration, as =destroy calls low level procs like gdk_event_unref(self.impl) above. So carefully sorting will be necessary. Note that forward declarations like below do not compile: proc gdk_event_unref(self: ptr Event00) proc gdk_event_unref(self: ptr Event00) {.importc, libprag.} Run Error: pragmas are only allowed in the header of a proc; redefinition of 'gdk_event_unref' Run What should work is declaring a special unref function before declaring the =destroy and using that one in the =destroy like proc destroy_gdk_event_unref(self: ptr Event00) {.importc: gdk_event_unref, libprag.} Run
Re: A good word for idiomatic nim?
nimatic
Re: Sorting JSON data by a specified field
`import json, algorithm let j = parseJson"""[{"id":"5","name":"A"}, {"id":"6","name":"C"}, {"id":"3","name":"B"}]""" let x = j.getElems.sorted(proc (a, b: JsonNode): int = cmp(a["name"].getStr, b["name"].getStr)) echo x # @[{"id": "5", "name": "A"}, {"id": "3", "name": "B"}, {"id": "6", "name": "C"}] ` Run
Re: Having problems porting a Python script for computing two cofactors of a number
Yes, there is definitely room for improvements. I just wanted to check if using bigints with minimal changes would be working. And I am actually surprised it does, since I was not able to find a gcd prox overloaded for BigInt (I was expecting to have to provide an implementation). Not sure what is being used there. Also, I I think in place addition and multiplication are not exported in bigints. Regarding the usage of stint, I would guess the actual Telegram protocol might go beyond uint64 and might have a specific size that one can work with.
Re: Idea why this does not compile?
I know why it doesn't compile but my reply would be identical to the compiler's error message. You need to define your destructor earlier, like so: when defined(gcDestructors): proc `=destroy`*(self: var typeof(Event()[])) = if not self.ignoreFinalizer and self.impl != nil: echo "gdk_event_unref(self.impl)" self.impl = nil template fnew*(a: untyped; finalizer: untyped) = when defined(gcDestructors): new(a) else: new(a, finalizer) proc `ref`*(self: Event): Event = fnew(result, generic_gdk_event_unref) echo "result.impl = gdk_event_ref(cast[ptr Event00](self.impl))" proc generic_gdk_event_unref*[T](self: ref T) = if not self.ignoreFinalizer: echo "gdk_event_unref(self.impl)" Run
Re: Having problems porting a Python script for computing two cofactors of a number
You need to use in-place addition and multiplication instead of out-of-place otherwise you will bottleneck on memory allocation/deallocation during all those loops with nim-bigint. If it fits in an uint64, stint is not needed, but otherwise as it's all stack allocated you won't suffer from allocation, the tradeoff is that you cannot have an arbitrary size.
Re: How to instantiate `ptr object`
The allure of undocumented behaviors ;) @dataPulverizer, if you already use pointers you can use generic procs, why do you need inheritance for dispatch?
Sorting JSON data by a specified field
OK, first of all I am very new to Nim. I have JSON data that I am retrieving via a REST API and I want to sort it based on a field in that data. The data looks something like this: [{"id":"582090251837636960","name":"Company 1","url":"[https://website.com/LeauObI/manage/organization/overview"}](https://website.com/LeauObI/manage/organization/overview"}), {"id":"60291940011422","name":"Company 10","url":"[https://website.com/o/2pFpYchb/manage/organization/overview"}](https://website.com/o/2pFpYchb/manage/organization/overview"}), {"id":"626000348204499553","name":"Company 3","url":"[https://website.com/o/2r9-dbWb/manage/organization/overview"}](https://website.com/o/2r9-dbWb/manage/organization/overview"})] I need to be able to sort this data by the "name" field. I have looked at the sort() function, but have not been able to figure out what needs to be done to get this data sorted. Has anyone done this or something similar? Thanks in advance.
Re: How to instantiate `ptr object`
> you can't mix inheritance with un-managed raw pointers. I can do it. In fact, I did in Nim's allocator.
Re: How to instantiate `ptr object`
> you can't mix inheritance with un-managed raw pointers. I can do it. In fact, I did in Nim's allocator.
Idea why this does not compile?
I was just working a bit on gintro for latest GTK4 and got a really confusing error message. Luckely I was just able to generate a minimal example, but I have still no real idea what the problem may be. I guess there must be something special in this code, because I have used similar constructs before and it was working fine... type Event* = ref object of RootRef impl*: pointer ignoreFinalizer*: bool template fnew*(a: untyped; finalizer: untyped) = when defined(gcDestructors): new(a) else: new(a, finalizer) proc `ref`*(self: Event): Event = fnew(result, generic_gdk_event_unref) echo "result.impl = gdk_event_ref(cast[ptr Event00](self.impl))" proc generic_gdk_event_unref*[T](self: ref T) = if not self.ignoreFinalizer: echo "gdk_event_unref(self.impl)" when defined(gcDestructors): proc `=destroy`*(self: var typeof(Event()[])) = if not self.ignoreFinalizer and self.impl != nil: echo "gdk_event_unref(self.impl)" self.impl = nil proc main = var x: Event fnew(x, generic_gdk_event_unref) main() Run $ nim c --gc:arc t2.nim /tmp/hhh/t2.nim(21, 3) Error: cannot bind another '=destroy' to: Event:ObjectType; previous declaration was constructed here implicitly: /tmp/hhh/t2.nim(13, 3) Run $ nim -v Nim Compiler Version 1.3.3 [Linux: amd64] Compiled at 2020-05-11 Copyright (c) 2006-2020 by Andreas Rumpf git hash: 7c24250a575b4d441ba6d7301714cbb246425fb6 active boot switches: -d:release Run
Re: How to instantiate `ptr object`
Isn't the point of inheritance method dispatch? Why isn't that a separate issue from objects that are dissociated from the garbage collector?
Re: Having problems porting a Python script for computing two cofactors of a number
Hi, out of curiosity I decided to do a naive "port" of the algorithm to use [https://github.com/def-/nim-bigints](https://github.com/def-/nim-bigints) Apart from the fact that doing that I ran into an issue with bigints ([https://github.com/def-/nim-bigints/issues/27](https://github.com/def-/nim-bigints/issues/27)) the result ([https://play.nim-lang.org/#ix=2lU5](https://play.nim-lang.org/#ix=2lU5)) works and on my machine compiled with `-d:danger` it takes a bit more than 500ms. It might also be interesting to use [https://github.com/status-im/nim-stint](https://github.com/status-im/nim-stint) instead of bigints.
Re: Game unlock gui written with gintro
Hey guys, a few days ago I've released version 0.9.3. In this version I'm using now glade and binding signals automatically. The source code and project structure is still not clean, because I never inteded to create a unlock gui (so please forgive me ;) ). The project will be delivered in the next version with a BF2142 mod. I also implemented multilingualism (but currently only in the gsparser branch). Please do not have a look into the `terminal.nim` file on the master branch, because it is a disaster (on gsparser branch I moved this into the main file `BF2142Unlocker.nim` and cleanuped this). This might be helpfull for some peoples that want to use glade and multililingualism on windows and linux. But be warned that I'm currently developing on the gspaser branch and that this currently does not compile on linux (but the master branch does).
Re: How to instantiate `ptr object`
> you can't mix inheritance with un-managed raw pointers That is an interesting point, I was wondering about it this morning already when I wrote my first reply. I am still not sure. I could generally imagine that inheritance can work with with un-managed raw pointers. But maybe not in Nim? @dataPulverizer note that create() may be easier to use, as with create() no cast is necessary. @snej The book is in a very early stage still, I wrote the two chapters in April. And it is mostly for people with very less programming experience.
Re: Nim version release notes?
For all changes in the latest devel (that's the development branch) you can read [https://github.com/nim-lang/Nim/blob/devel/changelog.md](https://github.com/nim-lang/Nim/blob/devel/changelog.md)
Re: How to instantiate `ptr object`
`ptr object of RootObj` seems very strange, you can't mix inheritance with un-managed raw pointers.
Nim version release notes?
I’ve been using Nim 1.2 so far, because it’s what Homebrew poured me, and because I figured it’s best to start with a stable release. But a lot of devs seem to use 1.3.x ... and I’m curious what new goodies it has. But I can’t find release notes or a what’s-new list anywhere. Is there such a thing? Or should I try diffing the nightly docs against the 1.2 ones? Or if someone just wants to reply and talk about their favorite new feature or improvement, that’s cool too :) —Jens
Re: How to parse html wild?
Browsers have _always_ supported “tag soup” HTML, back to Mosaic and Netscape. Unless the content type is XHTML, you cannot expect any sort of valid structure. For parsing “wild” HTML, preprocessing through some widely-used tidier is probably the best bet, since its interpretation of bad markup is hopefully similar to a browser’s.
Re: How to instantiate `ptr object`
I wasn’t aware of that book, though I’ve been guzzling from the Nim-documentation firehose for a week now. You should get it linked from the Nim-lang “learning” page!
Re: Terminal based GINTRO(GTK) VTE
In the last answer, the git shows how to make a console on the fly, and the possibility of executing a program in this console, basically this is what I do with termVte (in the example it is frozen but it was for my tests)
Re: Markdown test
We can already do italics and bold via * though, so it really isn't so bad. What is more annoying is the inability to respond with just a code block, those are bugs that need to be fixed.
Re: Markdown test
Thanks, except for those bold/italics, other rendering (especially the Markdown link syntax) is nicely supported in the newer nimforum version: [https://forum.my-toolbox.xyz/t/6](https://forum.my-toolbox.xyz/t/6)
Re: Is it possible for a macro to know the context it is used?
> Instead of having multiple small macros that don't play well together and > have only a local context, I'll apply a visitor-like pattern and I can > control the scopes in the DSL. Yes! Now you're cooking.
Re: Markdown test
I think more things will work after a redeploy of nimforum. :-)
Markdown test
Testing quote block: > some quote echo "hello" Run _[Italics](https://forum.nim-lang.org/postActivity.xml#italics) **Bold** _ **Bold and italics** _ [Nim website]([https://nim-lang.org](https://nim-lang.org)) ## heading level 2 ## heading level 3
Re: Having problems porting a Python script for computing two cofactors of a number
>From >[https://github.com/mratsim/number-theory/blob/12c54a7476327cf9ab00989c9964732e3eb68be7/src/modular_arithmetic.nim](https://github.com/mratsim/number-theory/blob/12c54a7476327cf9ab00989c9964732e3eb68be7/src/modular_arithmetic.nim) Modular addition proc addmod*[T: SomeInteger](a, b, m: T): T = ## Modular addition let a_m = if a < m: a else: a mod m if b == 0.T: return a_m let b_m = if b < m: b else: b mod m # We don't do a + b to avoid overflows # But we know that m at least is inferior to biggest T let b_from_m = m - b_m if a_m >= b_from_m: return a_m - b_from_m return m - b_from_m + a_m Run Modular multiplication proc mulmod*[T: SomeInteger](a, b, m: T): T = ## Modular multiplication var a_m = a mod m var b_m = b mod m if b_m > a_m: swap(a_m, b_m) while b_m > 0.T: if b_m.isOdd: result = addmod(result, a_m, m) #a_m = doublemod(a_m, m) a_m = (a_m shl 1) - (if a_m >= (m - a): m else: 0) b_m = b_m shr 1 Run Modular inversion (via GCD, so can return the GCD) proc invmod*[T:SomeInteger](a, m: T): T = ## Modular multiplication inverse ## Input: ## - 2 positive integers a and m ## Result: ## - An integer z that solves `az ≡ 1 mod m` # Adapted from Knuth, The Art of Computer Programming, Vol2 p342 # and Menezes, Handbook of Applied Cryptography (HAC), p610 # to avoid requiring signed integers # http://cacr.uwaterloo.ca/hac/about/chap14.pdf # Starting from the extended GCD formula (Bezout identity), # `ax + by = gcd(x,y)` # with input x,y and outputs a, b, gcd # We assume a and m are coprimes, i.e. gcd is 1, otherwise no inverse # `ax + my = 1` # `ax + my ≡ 1 mod m` # `ax ≡ 1 mod m`` # Meaning we can use the Extended Euclid Algorithm # `ax + by` with # a = a, x = result, b = m, y = 0 var a = a x = 1.T b = m y = 0.T oddIter = true # instead of requiring signed int, we keep track of even/odd iterations which would be in negative while b != 0.T: let (q, r) = divmod(a,b) t = x + q * y x = y; y = t; a = b; b = r oddIter = not oddIter if a != 1.T: # a now holds the gcd(a, m) and should equal 1 raise newException(ValueError, "No modular inverse exists") if oddIter: return x return m - x Run The whole point of proof-of-work is to have non-trivial computation. Factorizing small number is very fast hence you need them at a decent bit-width but if you're really desperate, I have an arbitrary bigint factorization algorithm in BrainFuck here ;): [https://github.com/numforge/laser/blob/d1e6ae61/examples/ex07_jit_brainfuck_src/factor.bf](https://github.com/numforge/laser/blob/d1e6ae61/examples/ex07_jit_brainfuck_src/factor.bf)
Re: Is it possible for a macro to know the context it is used?
Night has been enlightening. I understand my error. Instead of having multiple macros `algo1`, `evaluate`, etc. that are called when Nim compiler evaluates the syntax tree from the `dsl```call, I must see ``dsl` as a compiler itself. Now, I have only one macro, `dsl`, that is used to convert its argument to an AST, and then this AST is parsed/translated by procs in a new AST that will be used by the Nim compiler. Instead of having multiple small macros that don't play well together and have only a local context, I'll apply a visitor-like pattern and I can control the scopes in the DSL. Thanks @dawkot for forcing me to think out of the box with your example.
Re: Having problems porting a Python script for computing two cofactors of a number
> As far as I can see one of the issues if that there's an overflow when two > big uint64's are multiplied. Since after the multiplication you're taking a modulo, [these examples of modular arithmetic](https://en.wikipedia.org/wiki/Modular_arithmetic#Example_implementations) might come useful.
Re: Nimpy and Arraymancer
> Unfortunately that is a bug that is very hard to solve Ok, but the workaround is trivial, no? Just use `nimpy.callMethod` directly instead of the `.()` magic.
Re: Nimpy and Arraymancer
Uh wouldn't have guessed it would be such a complex issue actually. Well, thanks for the heads up, i'll just use non-generic proc.
Re: llegal capture 'world' because ':anonymous' has the calling convention:
`world` must be a parameter of your internal "closure". Either you use `{.closure.}` and when the compiler sees that `world` is capture from the external context it will allocate a copy on the heap. Or you use `{.nimcall.}` or `{.cdecl.}` and all the values captured must have a infinite lifetime (i.e. be globals) but in your case you are trying to capture `let world = world` which has the lifetime of the function.
Re: Is it possible for a macro to know the context it is used?
If there's a pattern of doing init(...), evaluate: ..., let ... = getValue(), then you can convert it to something like this: dsl: algo1 as x: echo x algo2(x) as y: echo y Run
llegal capture 'world' because ':anonymous' has the calling convention:
I am trying to define the following callback from Nim: static void nearCallback (void *data, dGeomID o1, dGeomID o2) { int i; //-- Get the body's ID dBodyID b1 = dGeomGetBody(o1); dBodyID b2 = dGeomGetBody(o2); //-- If they are connected by a joint, no collision detection is done. Finish if (b1 && b2 && dAreConnectedExcluding (b1,b2,dJointTypeContact)) { return; } //-- Configure the properties for the contact points dContact contact[MAX_CONTACTS]; for (i=0; i Run It is simply not possible or to do it because of the calling convention or is it that I am not doing the closure properly? Cheers
Re: Nimpy and Arraymancer
> That would be awesome ! Is there a way to call numpy API directly in > arraymancer or do you still use Nimpy ? No there is nothing for now.
Re: Nimpy and Arraymancer
After further investigation it's not a name conflict issue. This compiles import ../src/arraymancer import nimpy import nimpy/raw_buffers import sequtils proc `+`[T](p: ptr T, val: int) : ptr T {.inline.}= cast[ptr T](cast[uint](p) + cast[uint](val * sizeof(T))) proc pyBufToTensor[T](ndArray: PyObject): Tensor[T]= # Convert PyObject to RawPyBuffer var aBuf: RawPyBuffer ndArray.getBuffer(aBuf, PyBUF_WRITABLE or PyBUF_ND) aBuf.release() # Copy buffer into Tensor var shape: seq[int] for i in 0..https://github.com/yglukhov/nimpy/blob/b5401247](https://github.com/yglukhov/nimpy/blob/b5401247) /nimpy.nim#L1285-L1289| ---|--- template `.()`*(o: PyObject, field: untyped, args: varargs[untyped]): PyObject = dotCall(o, field, args) template `.`*(o: PyObject, field: untyped): PyObject = getAttr(o, astToStr(field)) Run So it does not have the opportunity to transform `np.reshape` into a wrapped call before Nim compiler tries to check if the reshape symbol is valid in generic procs. Unfortunately that is a bug that is very hard to solve.
Having problems porting a Python script for computing two cofactors of a number
Hello! So I decided to start trying to implement MTProto protocol (Telegram) in Nim, did the most basic things so I can get a reply from the server for the first time. To continue I need to decompose a number `pq` into two prime cofactors `p` and `q`, such as `p` < `q`. So basically I need to find the largest prime cofactor of a number and then divide the number by that cofactor to get the second one. The Python version I found runs really fast in under 100ms: from random import randint from math import gcd def brent(N): if N % 2 == 0: return 2 # y, c, m = randint(1, N - 1), randint(1, N - 1), randint(1, N - 1) y = 398563423414958448 c = 259203014236224986 m = 359097073186387306 g, r, q = 1, 1, 1 while g == 1: x = y for i in range(r): y = ((y * y) % N + c) % N k = 0 while k < r and g == 1: ys = y for i in range(min(m, r - k)): y = ((y * y) % N + c) % N q = q * (abs(x - y)) % N g = gcd(q, N) k = k + m r *= 2 if g == N: while True: ys = ((ys * ys) % N + c) % N g = gcd(abs(x - ys), N) if g > 1: break return g def factors(n): a = brent(n) b = n // a return (a, b) if a < b else (b, a) print(factors(1243804461473944423)) Run I tried my hand at porting it to Nim but I guess I failed: import random, math randomize() proc brent*(n: uint64): uint64 = if n mod 2 == 0: return 2 var # y = rand(1'u64 ..< n - 1) y = 398563423414958448'u64 c = 259203014236224986'u64 m = 359097073186387306'u64 g, r, q = 1'u64 x, k, ys = 0'u64 while g == 1: x = y for i in 0 ..< r: y = ((y * y) mod n + c) mod n k = 0'u64 while k < r and g == 1: ys = y for i in 0 ..< min(m, r - k): y = ((y * y) mod n + c) mod n q = q * uint64(abs(int64(x - y))) mod n g = gcd(q, n) k = k + m r *= 2 if g == n: while true: ys = ((ys * ys) mod n + c) mod n g = gcd(uint64(abs(int64(x - ys))), n) if g > 1: break result = g proc factors(n: uint64): (uint64, uint64) = let a = brent(n) let b = n div a if a < b: (a, b) else: (b, a) echo factors(1243804461473944423'u64) Run As far as I can see one of the issues if that there's an overflow when two big uint64's are multiplied. So can someone recommend a good way to port this algorithm, or maybe I can use some other algorithm which won't use such big numbers for multiplication? (I also tried porting [https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm](https://en.wikipedia.org/wiki/Pollard%27s_rho_algorithm) and succeeded, but it's quite slow)
Re: How to instantiate `ptr object`
I just wasn't sure whether when allocating for objects you have to account for any "gubbings", just cautious I guess: type MyTypeA = ptr object of RootObj x: int64 MyTypeB = ptr object of RootObj x: array[0..4, int64] var x0 = alloc(sizeof(int64)); var x1 = cast[MyTypeA](x0); x1.x = 42; echo "x: ", x1.x; dealloc(x1); # or dealloc(x0) var y0 = alloc(sizeof(int64)*5); var y1 = cast[MyTypeB](y0); y1.x = [1'i64, 2, 3, 4, 5]; echo "y1: ", y1.x; dealloc(y1); # or dealloc(y0) Run I've now added your book to my Nim reading list. Thanks
Re: Multithreading Pt 2.5: Nichecache
Ok, technically reason is not GC per se, but thread-local values cannot be accessed from other threads. Also, when cache is full, new items will overwrite old items (idea of FIFO ring buffer) and then they will be garbage collected. Here's a very simplified example that will cause SIGSEGV: from os import sleep type Cache = array[1, string] proc put(cache: ptr Cache) = cache[0] = "threadlocalstring" var sharedcache: Cache var thread: Thread[ptr Cache] createThread(thread, put, addr sharedcache) sleep(1000) # ensures that put happens here echo sharedcache[0] Run But the good news is that with --gc:arc this program works as expected.
Re: Multithreading Pt 2.5: Nichecache
I must admit that originally I wrote it this way by mistake. There goes my short-lived reputation as "the guy who invents really interesting AST hacks"... But the syntax stuck. In this rare occasion, it not only looks cool, it improves readability. Likely/unlikely is not an ordinary procedure call, for you it's a no-op, for me it's a reminder of where to (not) optimize, and for my compiler it's a hint of how to optimize.