Re: Object Variants and redefinition of labels or reusbility of field names
Another workaround type # The 3 notations refer to the same 3-D entity, and some coordinates are shared CoordinateSystem = enum csCar, # Cartesian(x,y,z) csCyl, # Cylindrical (r,φ,z) csSph # Spherical(ρ,θ,φ) Coordinates = object cs: CoordinateSystem # cs is the coordinate discriminator coor1, coor2, coor3: float # keep this part private CoorException* = ref object of Exception proc x(p: Coordinates): float = if p.cs != csCar: raise newException(Defect, "Only available for Cartesian.") p.coor1 proc `x=`(p: var Coordinates, xval: float) = if p.cs != csCar: raise newException(Defect, "Only available for Cartesian.") p.coor1 = xval # do the same with y, and z, should be succint with templates proc φ*(p: Coordinates): float = if p.cs == csCar: raise newException(Defect, "Cartesian doesn't support φ field.") elif p.cs == csCyl: result = p.coor2 elif p.cs == csSph: result = p.coor3 # do the same with other field var car1 = Coordinates(cs: csCar, coor1: 1.0, coor2: 2.0, coor3: 3.0) echo car1.x car1.x = 1.5 echo car1.x var car2 = Coordinates(cs: csCyl, coor1: 1.0, coor2: 2.0, coor3: 3.0) echo car2.φ Run Read more about it in [manual page here](https://nim-lang.github.io/Nim/manual.html#procedures-properties)
Re: Object Variants and redefinition of labels or reusbility of field names
workaround import strformat type # The 3 notations refer to the same 3-D entity, and some coordinates are shared CoordinateSystem = enum csCar, # Cartesian(x,y,z) csCyl, # Cylindrical (r,φ,z) csSph # Spherical(ρ,θ,φ) Cartesian = object x, y, z: float Cylindrical = object r, phi, z: float Spherical = object rho, theta, phi: float Coordinates = object case cs: CoordinateSystem: # cs is the coordinate discriminator of csCar: car: Cartesian of csCyl: cy: Cylindrical of csSph: sph: Spherical proc `$`(point: Coordinates): string = case point.cs of csCar: result = &"(x: {point.car.x:5.2f}, y: {point.car.y:5.2f}, z: {point.car.z:5.2f})" of csCyl: result = &"(r: {point.cy.r:5.2f}, φ: {point.cy.phi:5.2f}, z: {point.cy.z:5.2f})" of csSph: result = &"(ρ: {point.sph.rho:5.2f}, θ: {point.sph.theta:5.2f}, φ: {point.sph.phi:5.2f})" Run
Re: Why is -1 mod 5 not equal to 4? (it is -1)
It starts to make sense when you think about it. 1) The operator div and mod have to be consistent with each other in such a way that: if d = a div b, and m = a mod b, then a = d*b + m. 2) By the other hand, div needs to be consistent with the sign in a division, so if d = a div b and only one of the operands a or b is negative, then the result d needs to be negative, otherwise is positive. >From 1 and 2, there's only one possible result for div, and so, mod is left >with one choice too. The following table (if you run it) will start to make more sense. See also some sort of consistency around zero. var a, b, c, d, m: int proc i2s(i: int): string = if i >= 0: result &= " " result &= $i proc test(b: int) = var line: string echo "for b = ", i2s(b) for a in -9 .. 9: line = "" d = a div b m = a mod b c = b*d + m line &= " a = " & i2s(a) line &= " d = (" & i2s(a) & " div " & i2s(b) & ") = " & i2s(d) line &= " m = (" & i2s(a) & " mod " & i2s(b) & ") = " & i2s(m) line &= " (" & i2s(b) & " * (" & i2s(d) & ") + (" & i2s(m) & ")) = " & i2s(c) line &= " == a ? --> " & $(c==a) echo line test(5) echo "" test(-5) Run the output is: for b = 5 a = -9 d = (-9 div 5) = -1 m = (-9 mod 5) = -4 ( 5 * (-1) + (-4)) = -9 == a ? --> true a = -8 d = (-8 div 5) = -1 m = (-8 mod 5) = -3 ( 5 * (-1) + (-3)) = -8 == a ? --> true a = -7 d = (-7 div 5) = -1 m = (-7 mod 5) = -2 ( 5 * (-1) + (-2)) = -7 == a ? --> true a = -6 d = (-6 div 5) = -1 m = (-6 mod 5) = -1 ( 5 * (-1) + (-1)) = -6 == a ? --> true a = -5 d = (-5 div 5) = -1 m = (-5 mod 5) = 0 ( 5 * (-1) + ( 0)) = -5 == a ? --> true a = -4 d = (-4 div 5) = 0 m = (-4 mod 5) = -4 ( 5 * ( 0) + (-4)) = -4 == a ? --> true a = -3 d = (-3 div 5) = 0 m = (-3 mod 5) = -3 ( 5 * ( 0) + (-3)) = -3 == a ? --> true a = -2 d = (-2 div 5) = 0 m = (-2 mod 5) = -2 ( 5 * ( 0) + (-2)) = -2 == a ? --> true a = -1 d = (-1 div 5) = 0 m = (-1 mod 5) = -1 ( 5 * ( 0) + (-1)) = -1 == a ? --> true a = 0 d = ( 0 div 5) = 0 m = ( 0 mod 5) = 0 ( 5 * ( 0) + ( 0)) = 0 == a ? --> true a = 1 d = ( 1 div 5) = 0 m = ( 1 mod 5) = 1 ( 5 * ( 0) + ( 1)) = 1 == a ? --> true a = 2 d = ( 2 div 5) = 0 m = ( 2 mod 5) = 2 ( 5 * ( 0) + ( 2)) = 2 == a ? --> true a = 3 d = ( 3 div 5) = 0 m = ( 3 mod 5) = 3 ( 5 * ( 0) + ( 3)) = 3 == a ? --> true a = 4 d = ( 4 div 5) = 0 m = ( 4 mod 5) = 4 ( 5 * ( 0) + ( 4)) = 4 == a ? --> true a = 5 d = ( 5 div 5) = 1 m = ( 5 mod 5) = 0 ( 5 * ( 1) + ( 0)) = 5 == a ? --> true a = 6 d = ( 6 div 5) = 1 m = ( 6 mod 5) = 1 ( 5 * ( 1) + ( 1)) = 6 == a ? --> true a = 7 d = ( 7 div 5) = 1 m = ( 7 mod 5) = 2 ( 5 * ( 1) + ( 2)) = 7 == a ? --> true a = 8 d = ( 8 div 5) = 1 m = ( 8 mod 5) = 3 ( 5 * ( 1) + ( 3)) = 8 == a ? --> true a = 9 d = ( 9 div 5) = 1 m = ( 9 mod 5) = 4 ( 5 * ( 1) + ( 4)) = 9 == a ? --> true for b = -5 a = -9 d = (-9 div -5) = 1 m = (-9 mod -5) = -4 (-5 * ( 1) + (-4)) = -9 == a ? --> true a = -8 d = (-8 div -5) = 1 m = (-8 mod -5) = -3 (-5 * ( 1) + (-3)) = -8 == a ? --> true a = -7 d = (-7 div -5) = 1 m = (-7 mod -5) = -2 (-5 * ( 1) + (-2)) = -7 == a ? --> true a = -6 d = (-6 div -5) = 1 m = (-6 mod -5) = -1 (-5 * ( 1) + (-1)) = -6 == a ? --> true a = -5 d = (-5 div -5) = 1 m = (-5 mod -5) = 0 (-5 * ( 1) + ( 0)) = -5 == a ? --> true a = -4 d = (-4 div -5) = 0 m = (-4 mod -5) = -4 (-5 * ( 0) + (-4)) = -4 == a ? --> true a = -3 d = (-3 div -5) = 0 m = (-3 mod -5) = -3 (-5 * ( 0) + (-3)) = -3 == a ? --> true a = -2 d = (-2 div -5) = 0 m = (-2 mod -5) = -2 (-5 * ( 0) + (-2)) = -2 == a ? --> true a = -1 d = (-1 div -5) = 0 m = (-1 mod -5) = -1 (-5 * ( 0) + (-1)) = -1 == a ? --> true a = 0 d = ( 0 div -5) = 0 m = ( 0 mod -5) = 0 (-5 * ( 0) + ( 0)) = 0 == a ? --> true a = 1 d = ( 1 div -5) = 0 m = ( 1 mod -5) = 1 (-5 * ( 0) + ( 1)) = 1 == a ? --> true a = 2 d = ( 2 div -5) = 0 m = ( 2 mod -5) = 2 (-5 * ( 0) + ( 2)) = 2 == a ? --> true a = 3 d = ( 3 div -5) = 0 m = ( 3 mod -5) = 3 (-5 * ( 0) + ( 3)) = 3 == a ? --> true a = 4 d = ( 4 div -5) = 0 m = ( 4 mod -5) = 4 (-5 * ( 0) + ( 4)) = 4 == a ? --> true a = 5 d = ( 5 div -5) = -1 m = ( 5 mod -5) = 0 (-5 * (-1) + ( 0)) = 5 == a ? --> true a = 6 d = ( 6 div -5) = -1 m = ( 6 mod -5) = 1 (-5 * (-1) + ( 1)) = 6 == a ? --> true a = 7 d = ( 7
Re: Why is -1 mod 5 not equal to 4? (it is -1)
Actually, you ask 2 questions, the title is only the 1st. ;-) The answer to the first question is that `mod` translates to C's `%`, and the specification for `%` in C is that negative numbers gives negative results; that is, `-5 % 4 == 1` in C. I can think of more than one answer to the second question. The simplest (?) is probably to take the absolute value before computing the modulus: var a = -5 var b = 4 echo a mod b # gives -1 echo abs(a) mod b # gives 1 Run
Object Variants and redefinition of labels or reusbility of field names
This is a case in which it would be desirable that some fields in object variants could share the name and hence, its value. In the following example, my first two attempts: Coordinates_1 and Coordinates_2, were typed intuitively, but failed to compile one after another due to the restrictions imposed to object variants. The third attempt is the Coordinates object variant, and it works as designed, but lacks the flexibility for a more readable and intuitive definition, which ends up with additional names and cryptic implementation of the corresponding operators and procedures. Please give me hope that there are plans or works to allow this possibility. In fact, the nicer and more readable one would be that of Coordinates_1. type # The 3 notations refer to the same 3-D entity, and some coordinates are shared CoordinateSystem = enum csCar, # Cartesian(x,y,z) csCyl, # Cylindrical (r,φ,z) csSph # Spherical(ρ,θ,φ) #[ Attempt 1: fails to compile due to redefinition of z and phi Coordinates_1 = object case cs: CoordinateSystem: # cs is the coordinate discriminator of csCar: x: float y: float z: float of csCyl: r: float phi: float z: float # cy_z is the same as Cartesian z, but cannot duplicate labels of csSph: rho: float theta: float phi: float # sp_phi is the same as Cylindrical phi, but cannot duplicate labels ]# #[ Attempt 2: fails to compile due to duplication of labels Coordinates_2 = object case cs: CoordinateSystem: # cs is the coordinate discriminator of csCar: x: float y: float of csCar, csCyl: z: float # both csCat and csCyl share z of csCyl: r: float of csCyl, csSph: phi: float # both csCyl and csSph share phi of csSph: rho: float theta: float ]# # this definition works but does not allow to share fields that represent the same entity Coordinates = object case cs: CoordinateSystem: # cs is the coordinate discriminator of csCar: x: float y: float z: float of csCyl: r: float phi: float cy_z: float # the same as Cartesian z, but cannot share its name of csSph: rho: float theta: float sp_phi: float # the same as Cylindrical phi, but cannot share its name proc coordinates(coordSys: CoordinateSystem; arg0, arg1, arg2: float): Coordinates = case coordSys: of csCar: return Coordinates(cs: csCar, x: arg0, y: arg1, z: arg2) of csCyl: return Coordinates(cs: csCyl, r: arg0, phi: arg1, cy_z: arg2) of csSph: return Coordinates(cs: csSph, rho: arg0, theta: arg1, sp_phi: arg2) proc `$`(point: Coordinates): string = result = "(" case point.cs: of csCar: result &= "x:" & $point.x & ", y:" & $point.y & ", z:" & $point.z of csCyl: result &= "r:" & $point.r & ", φ:" & $point.phi & ", z:" & $point.cy_z of csSph: result &= "ρ:" & $point.rho & ", θ:" & $point.theta & ", φ:" & $point.sp_phi result &= ")" echo coordinates(csCar, 1, 2, 3) #output: (x:1.0, y:2.0, z:3.0) echo coordinates(csCyl, 4, 5, 6) #output: (r:4.0, φ:5.0, z:6.0) echo coordinates(csSph, 7, 8, 9) #output: (ρ:7.0, θ:8.0, φ:9.0) Run
Object Variants and some issues
It sounds reasonable that the discriminator of an object variant should be kept invariable to keep the object's data structure safe; I found, however, some scenarios in which it can be done. One way was to use the compiler directive --fieldChecks:off. I also attempted the same, but using the pragma {.fieldChecks: off.} and it worked. In fact I just found about that pragma by intuition, as it's not documented anywhere as far as I could research. I learnt also that you can use the pragma {.fieldChecks: on.} to bring back checking after the "unsafe" procedures are declared. I assume that "unsafe" procedures are all those that may use the discriminator once it has been changed. For example, in the code below, type MyKind = enum mk1, mk2 MyObj = object case mk: MyKind: of mk1: x, y, z: float of mk2: u, v, w: float proc myProc(mk: MyKind; i, j, k: float): MyObj = case mk: of mk1: return MyObj(mk: mk1, x: i, y: j, z: k) of mk2: return MyObj(mk: mk2, u: i, v: j, w: k) {.fieldChecks: off.} # disable field checks for object variants proc change(mo: var MyObj; mkTo: MyKind) = # this is an unsafe proc that changes the discriminator # so the fieldChecks must me turned off to avoid runtime errors mo.mk = mkTo {.fieldChecks: on.} # turn field checks back on {.fieldChecks: off.} # disable field checks again, this proc `$` seems to fail at runtime otherwise proc `$`(mo: MyObj): string = # seemingly because of the previous proc, `$` also needs fieldChecks off # this can be made public* as it is safe to use result = "[mk: " & $mo.mk & "]:(" case mo.mk: of mk1: result &= "x:" & $mo.x & ", y:" & $mo.y & ", z:" & $mo.z of mk2: result &= "u:" & $mo.x & ", v:" & $mo.y & ", w:" & $mo.z result &= ")" {.fieldChecks: on.} # turn field checks back on proc rotate(mo: var MyObj) = # rotates the contents of mo regardless of what kind it is # this proc seems not to require fieldChecks turned off var temp: float orik: MyKind = mo.mk # this is the original kind change(mo, mk1) # temporary kind change # all kinds are treated as mk1, so less code is required temp = mo.x mo.x = mo.y mo.y = mo.z mo.z = temp change(mo, orik) # kind back to the original kind var p, q: MyObj p = myProc(mk1, 1, 2, 3) # p starts as kind "mk1" echo "p = ", p# output: p = [mk: mk1](x:1.0, y:2.0, z:3.0) change(p, mk2)# p is changed to kind "mk2" echo "p = ", p# output: p = [mk: mk2](u:1.0, v:2.0, w:3.0) rotate(p) # parameters of P are rotated echo "p = ", p# output: p = [mk: mk2](u:1.0, v:2.0, w:3.0) q = myProc(mk2, 4, 5, 6) # q starts as kind "mk2" echo "q = ", q# output: q = [mk: mk2](u:4.0, v:5.0, w:6.0) rotate(q) # parameters of q are rotated echo "q = ", q# output: q = [mk: mk2](u:5.0, v:6.0, w:4.0) Run
Nimph is a Nim package handler for the rest of us
I'm about to go out of town and offline for the holiday, so I thought this would be a great time to drop a URL and then be unavailable to answer questions or fix bugs! [https://github.com/disruptek/nimph](https://github.com/disruptek/nimph) But seriously, it's getting to that point where it needs wider testing to find bugs and stupid design decisions. If you use Git and GitHub heavily, then I think you'll really like this. If you also wished for local dependencies or lockfiles, then you'll be very happy indeed. Finally, if you're lazy, I think you'll find that I have your number. ;-)
Why is -1 mod 5 not equal to 4? (it is -1)
The Title is the Question :D. I know that there is mod and %%. %% is only for unsigned integers, so i thought mod would also work with signed ones. What is the operator or function i need to get the correct modulus?
Re: How to set a specific file as main file in VS Code ?
I use for the project a .sh file or a makefile or .bat
Re: What’s your favorite programming language and why?
for me quite the opposite once the modules are well understood the same module for all managed like set theory
How to parse RSS feeds with Nim
I'm learning Nim and as I learned things, I'm writing blog posts about common stuff you would do with Nim. This is an effort to get Nim more mainstream attention by other engineers looking for something powerful to add to their toolbelt. In this first blogpost, I show you how to parse a typical RSS feed using Nim. Thanks! [https://sergio.dev/posts/how-to-parse-rss-feeds-with-nim](https://sergio.dev/posts/how-to-parse-rss-feeds-with-nim)
Re: Walking trees without recursive iterators
Ok, I understand what's the problem with the condition and can reproduce the bug in a unit test. These are my thoughts about possible fixes: * As far as I can tell, the only way to recognize that the client of the iterator has deleted a child, is checking the number of children in the parent between iterations. I think this would require another stack with the number of children of each parent node and adjusting this for each iteration. I don't think I can pull this off. I was already struggling with the current implementation. Even if all unit tests passed, I don't think I would trust the code. * I thought of instead of putting regular `XMLNode` s in the yielded object, put some wrapper object there that would track `delete` calls. The iterator could then ask the previously yielded object whether `delete` was called on it and adjust the iterator. I haven't yet thought about in detail how this would work. Actually I won't, because this approach would probably cause a lot of problems, the most obvious if client code checks a yielded "XMLNode" for its type. * Implementing a variant of the first approach with the "traditional" [iterator pattern](https://en.wikipedia.org/wiki/Iterator_pattern). That is, instead of maintaining stacks "manually", I'd define iterator objects with some state and a `next` proc. Since this iterator wouldn't use Nim's `iterator` but procs, I could nest these iterators. With this approach, I have more hope that this would give a reliable implementation. Now, in my code I use this iterator only in one proc and I assume it will be _much_ simpler to merge the iterator into the proc and be confident in the result. Someone more experienced with Nim than I :-) suggested to me that such an iterator would still be nice to have for others. What do you think? Besides, when I was debugging the iterator to get to the point even _with_ the bug, I ran into the following problems: * The obvious one is that the implementation would probably have been much easier if I could nest iterators. * I found [using gdb](https://internet-of-tomohiro.netlify.com/nim/gdb.en.html#debug-simple-program-with-gdb) (even with Nim's `nim-gdb.py`) on the nested data structures on the C level so awkward that in the end I relied more on `debugEcho` statements than on the debugger. It's not that I have a problem with command-line debuggers. I've used Python's `pydb` many times which has a similar interface as gdb and I actually like it. I'd appreciate it a lot if there was a debugger that worked more on the "Nim level".
Re: understanding risk of shadowing
yes It should be identical, thank you! was a c leftover, where I used trunc(log10(i) + 1) :D
Re: Problem with C interop/X11 bindings
there is no nil, it reports wrong size.
Re: Problem with C interop/X11 bindings
thats how bindings define that proc. and it doesn't matter in that case, its just an array index.
Re: Problem with C interop/X11 bindings
Why that keycode.int16 in Nim code? Seems that C-code passes cint.
Re: Problem with C interop/X11 bindings
Idk too, but try to wrap the functionality in some proc like main or anything and just call that proc. Another thing, you can always use gdb to check each variable which one has nil.
Problem with C interop/X11 bindings
I have two snippets, in C and Nim which _supposed_ to be exact copies of eachother. #include #include #include typedef struct keymap { int keycode_high; int keycode_low; } keymap_t; keymap_t keymap_new(Display *dpy) { keymap_t result; XDisplayKeycodes(dpy, &(result.keycode_low), &(result.keycode_high)); XkbDescPtr desc = XkbGetMap(dpy, XkbAllClientInfoMask, XkbUseCoreKbd); for (int keycode = result.keycode_low; keycode <= result.keycode_high; keycode++) { int groups = XkbKeyNumGroups(desc, keycode); printf("%d\n", groups); } XkbFreeClientMap(desc, 0, 1); return result; } int main(){ Display *dpy = XOpenDisplay(NULL); keymap_t x = keymap_new(dpy); XCloseDisplay(dpy); } Run import x11/[xlib, xkblib] import x11/xkb except X_kbGetMap type Keymap = object keycodeHigh, keycodeLow: cint proc newKeymap(display: PDisplay): Keymap = discard XDisplayKeycodes(display, addr result.keycodeLow, addr result.keycodeHigh) let desc = XkbGetMap(display, XkbAllClientInfoMask, XkbUseCoreKbd) for keycode in result.keycodeLow..result.keycodeHigh: let groups = XkbKeyNumGroups(desc, keycode.int16) echo groups XkbFreeClientMap(desc, 0, true) let display = XOpenDisplay(nil) keymap = newKeymap(display) discard XCloseDisplay display Run They are supposed to have same output, but it differs, which in nim version can lead to segfaults in further usage of returned data. I looked at structure definitions in bindings and they seem correct, so im out of ideas now.
Re: understanding risk of shadowing
Is trunc(float(n mod 10)).int not identical to plain n mod 10? And you may use for i in countdown(5, 0) if you like.
Re: understanding risk of shadowing
thanks @juancarlospaco and @doofenstein! I've red the manual but totally forgot about the implicit result variable.
How to set a specific file as main file in VS Code ?
Hi all, This is a vs code special question rather than a nim question. I have 10 nim files in a folder and i want one file ( say test.nim) to run always. But when i edit any of the 9 files, i need to activate the main file in order to run. Is there any way to set the test.nim as main file so that i can press the run button no matter which file is active ? I am using coderunner extension. I know that i can set the test.nim in coderunner's setting, but then i won't be able to run other project files in vs code.
Re: understanding risk of shadowing
As @juancarlospaco said, Nim has an implicitly declared result variable. It is zero like all variables zero initialised and returned by default which is great to remove some boilerplate code: import math proc toNumArray(n: int): array[6, int] = var n = n for i in 0..<6: result[5-i] = trunc(float(n mod 10)).int n = n div 10 echo toNumArray(123456) Run See also: [https://nim-lang.org/docs/manual.html#statements-and-expressions-return-statement](https://nim-lang.org/docs/manual.html#statements-and-expressions-return-statement)
Re: understanding risk of shadowing
Nothing wrong with `n`. All `proc` and `func` have an automatic `result` variable created from the type on the signature of the function. Change `var result =` to `result =`
understanding risk of shadowing
I try to understand **Warning: Special variable 'result' is shadowed. [ResultShadowed]** in following code: import math proc toNumArray(n: int): array[6, int] = var n = n var result = [0, 0, 0, 0, 0, 0] for i in 0..<6: result[5-i] = trunc(float(n mod 10)).int n = n div 10 result echo toNumArray(123456) Run I know shadowing is used, because parameter are immutable. So I got some questions about shadowing 1. I shadow **n** are there some drawbacks of doing so? 2. Why is **result** shadowed? And also, what are the drawbacks? 3. Is there a better way to accomplish this is Nim?
Re: Looking for help with IntelliJ Plugin
Just a little update, I'm not a huge fan of IntelliJ's GrammerKit, I probably should have used Antlr and used the Antlr Adapter but the performance would most likely suffer quite a bit. I haven't really worked on the error recovery yet. Still looking for volunteers of all types including constructive criticism.
Re: Proc and Iterators with Result Variable
I also noticed that the return statement in typed procs turns return 5 Run into return result = 5 Run which is invalid code if you turn the result variable into an ident. This should probably be documented better as well.
Proc and Iterators with Result Variable
I noticed when I took getImpl of a typed closure or proc there was an extra node dedicated to the result variable. Not noticing it led to some truly confusing error messages when I was trying to take an existing proc and make a new proc derived from it. I would suggest adding an extra slot into untyped procDefs that will be newEmptyNode() when the proc hasn't been typed yet. Or at the very least this feature should be better documented in macros.nim.