Re: [Suggestion] A syntactic sugar for cast.
You may read again the manual section ncrosby cited, or read tutorial: [https://nim-lang.org/docs/tut2.html#object-oriented-programming-type-conversions](https://nim-lang.org/docs/tut2.html#object-oriented-programming-type-conversions) In Nim we generally avoid casts, but we may do type conversion: if obj of Child: let child = Child(obj) Run
Set of enums with holes
Recently someone complained about gintro not working well with latest Nim devel. Well not too surprising due to a few breaking changes. [https://github.com/StefanSalewski/gintro/issues/28](https://github.com/StefanSalewski/gintro/issues/28) I have just tried to try it with latest devel -- do not yet see the gorge issue, but can see this minor problem when compiling gintro/glib.nim type TestTrapFlag* {.size: sizeof(cint), pure.} = enum ignoreThisDummyValue = 0 #ignoreThisDummyValue1 = 1 #ignoreThisDummyValue2 = 2 #ignoreThisDummyValue3 = 3 #ignoreThisDummyValue4 = 4 #ignoreThisDummyValue5 = 5 #ignoreThisDummyValue6 = 6 silenceStdout = 7 silenceStderr = 8 inheritStdin = 9 TestTrapFlags* {.size: sizeof(cint).} = set[TestTrapFlag] Run $ nim c t.nim Hint: used config file '/home/stefan/Nim/config/nim.cfg' [Conf] Hint: system [Processing] Hint: t [Processing] t.nim(15, 46) Error: ordinal type expected Run For Nim <= 0.18 it was necessary to have ignoreThisDummyValue = 0 to be compatible with intended C flags. Now it seems not to compile any more due to the holes. When I add all the commented dummy bits it seems to compile again. Do I have to fix the generator script to add all that dummy values for all the related gtk3 flags?
Re: Generating pascal interface
I think what you wants to do is plain text processing. For that you do not need Nim macros, you may use module strutils and related modules, maybe also pattern matching. Basically you parse the input nim file, and then write the pascal interface file with that data.
Re: Going to Haxe. Nim In Action book available.
> Got it. I will bookmark it in my mail folder, so i can send you the book > later. Why that effort? See google or Manning page: [https://account.manning.com/support](https://account.manning.com/support) Section shipping: I need to change my shipping address on a pending order. Please send a message to supp...@manning.com and we can update your address for all pending orders.
Re: nim-ffmpeg wrapper: how to continue?
Yes, the reordering can be much manual work. For the gintro module, I do it automatically now, but it takes a few minutes to finish -- and it is based on gobject-introspection. The ugly way is to put all types into a single type section at the front of the module. Many modules from early days like the gtk2 ones do that. But of course that is mud mixing, the resulting module is very unfriendly for the human observer. Someone recommended in the past to ship one mudmixed module for the compiler and one virgin one for humans. You may do that. Or, you may ask Araq for the pragma name which allows forward declarations. I tested it one year ago, it was working fine indeed. But was not really advertised or recommended. Or, you may wait -- future compiler versions may support forward declarations out of the box.
Re: Differences: Object variant vs static conditional fields
You can store variables of type Node all in one single seq. For node2: I really think that there is no way to store variables of type Node2[nkInt] and Node2[nkFloat] in the same seq. So Node 1 is more dynamic. But I am not really sure, have never used object variants...
Re: completely new to programming
> I say this as someone who spent decades writing C code So you did exactly what I suggest Of course it is difficult to make suggestions to puwad as we don't know him. But starting with Nim TODAY for a real beginner is really hard. And Nim in Action is not a book teaching Nim for beginners. The Nim tutorial may be OK for a really smart beginner, maybe. Generally people who start with higher level languages like Java, Ruby, Python and never learned a real low level language are doing some really stupid stuff later from time to time ore are asking some really stupid questions -- as they have no feeling what a computer really is and what it does. 30 years ago there was Pascal as a teaching language for beginners, a mix of low level language with some higher level components. But learning Pascal would be waste of time today. Now most students seems to start with Java -- well not a nice language, but it will help finding a job, even for people who do not get a degree as the left after a few semesters.
Re: Partial casing is foo_bar
@cdunn2001 > partial-casing causes problems. Can you provide examples? For the gtk related libs, I had initially indeed problems two years ago when Nimrod was fully style insensitive. But now with partial casing there are no problems, types like Buffer start with capital letter, and procs or templates are written buffer(). (Indeed it was not that easy, there where private C types with underscore like _buffer which are mapped to public types without underscore -- but I was able to solve that with text substitution scripts.) If you can provide examples with real problems: I suggested long time ago to allow underscore as first or last character of an identifier and use that as the same time to indicate that this identifier is fully case sensitive. That is easy to implement and allows to fix ALL of the rare real problems.
Fun with deduplicate
I wonder if sequtils.deduplicate() should be renamed to deduplicated() as it returns a seq like sorted()? And maybe it should be noted that it is O(n^2), which is fine for small collections, but not so nice for large ones. And maybe we should add a O(n) deduplicate to stdlib -- sets modul is really fast as shown below. import sets import random, times import sequtils # deduplicate # O(n) proc uniqCopy[T](s: openArray[T]): seq[T] = let h = s.toOrderedSet newSeq(result, h.len) # can we avoid the unnecessary initialization? var i = 0 # is there no items with index for sets? for el in h: result[i] = el inc(i) # O(n) proc uniq[T](s: var seq[T]) = let h = s.toOrderedSet var i = 0 for el in h: s[i] = el inc(i) s.setLen(h.len) # O(n^2) proc xdeduplicate[T](s: var seq[T]) = var i, j: int while i < s.len: s[j] = s[i] var k = j while k > 0: dec k if s[k] == s[j]: dec(j) break inc(j) inc(i) s.setlen(j) var a = @[1, 3, 1, 2, 2, 5, 2] var b = a echo a.uniqCopy a.xdeduplicate b.uniq echo a echo b var t: float # cpuTime() var x: array[1000, int] for el in mitems(x): el = random(1000) var z = @x t = cpuTime() z = z.deduplicate echo "sequtils.dedublicate: ", cpuTime() - t z = @x t = cpuTime() z.xdeduplicate echo "inplace dedublicate: ", cpuTime() - t z = @x t = cpuTime() z = z.uniqCopy echo "uniqCopy: ", cpuTime() - t z = @x t = cpuTime() z.uniq echo "uniq: ", cpuTime() - t # nim c -d:release t.nim # Output # @[1, 3, 2, 5] # @[1, 3, 2, 5] # @[1, 3, 2, 5] # sequtils.dedublicate: 0.0001411 # inplace dedublicate: 0.0001329 # uniqCopy: 3.099e-05 # uniq: 2.711e-05
Re: Nim in Action is now available!
I just got version 9 of the meap. I was curious about the actual improvement work of the manning people. My early expectation was that they would not do much, indeed I think they can not do much, just because they do not understand the matter. So only a few grammar fixes remain to them, and I have the feeling that is what they did. But they still have not discovered that in the "Welcome" preface there are still 10 chapters mentioned, while we all know that only 9 are left. And in the first chapter this weak paragraph is still present: " One feature of the language makes it particularly well suited to systems programming. You will find that Nim is a compiled language, but the way in which it is compiled is special. When source code is compiled by the Nim compiler, it is first translated into C code. C is a pretty old but well supported systems programming language; because of this, more direct and easier access to the physical hardware of the machine is allowed. As such, Nim is very well suited to writing operating systems, compilers, device drivers, embedded system software, and more. ... Applications written in Nim are very fast, in many cases just as fast as applications written in C and more than 13 times faster than applications written in Python. " Of course that is not really wrong and most of us do know what Dom wants to express, but it is a very weak wording. And exactly 13 times -- funny. So I wonder what the Manning contribution to the books is?
Re: Extending objects and initialization
That is very interesting, thanks. (As you know, I am using your module combinatorics.nim in [https://github.com/StefanSalewski/nim-gi2](https://github.com/StefanSalewski/nim-gi2). Would be nice if that module would be put into Nim's standard lib -- it works fine, but I have never tried to understand it yet, I guess it is not trivial...)
Re: How to implement a dynamic array
> I got a Data Structures book Which book do you have? Do you like it? > I know how to do it with Java Can you show us your code? I would like to learn how to do it in Java. Basically, what you need to build something like Nim's seq is allocating chunks of memory from the OS. You may inspect Nim's low level modules to find it out. But of course there exists much more interesting and useful data structures to build. Maybe a robin hood or hopscotch ordered hash table (I was playing recently with that) or some of the structures boost lib has?
Re: Games made in Nim
[https://forum.nim-lang.org/t/2924#18358](https://forum.nim-lang.org/t/2924#18358) [https://github.com/StefanSalewski/nim-chess3](https://github.com/StefanSalewski/nim-chess3) [https://github.com/fragworks/frag](https://github.com/fragworks/frag) I think there are already more, some commercial seems to be in development.
Re: Full nimble support for gintro package (high level GTK3 GUI) available
Should work for Windows 10 also now. As Araq recommended, I removed the single quotes in the wget and nimgrab command strings. You just have to ensure that all needed GTK3 libs are installed on your Windows box before gintro install. You may follow user zetashift's advise, but don't forget to install the separate file https://github.com/Alexpux/MINGW-packages/blob/master/mingw-w64-gtksourceview3
Re: Nim GC Performance
Thanks for the link, sounds interesting, will read soon... For your test code, I am not really sure what the purpose is. Nim's realtime GC is tunable, so you can get very short pause time with a tradeoff in throughput. See [http://nim-lang.org/docs/gc.html](http://forum.nim-lang.org///nim-lang.org/docs/gc.html) You seems to test only only pause time for the default, which may be more tuned to throughput. (For my understanding, for most software pause times are not critical, or at least pause times of a few ms are fully OK, as for action games. For hardware control pauses may be critical, but if we do not allocate GC memory in critical parts, then the GC will not run in that critical part.) And when you are testing, you may test the boehm Gc as well. I hope my understanding is not too wrong, I have newer spent time investigationg or understanding the GC. For your code itself there is some room for improvement of course, for example for i in items( result[] ): result[i] = byte( n ) should be writable as for i in mitems( result[] ): i = byte( n )
Re: Compiler crashes while compiling module with
> I managed to reduce the crash to this Great. Maybe test if it only occurs for Natural or also for int, and create an issue for github issue tracker. Should be a task for Zachary.
Why is integer multiplication so slow here?
proc main = var s = 0 for i in 0 .. 10: if i * i == 49: #if i == 7: s += 1 echo s main() For this test, using "if i == 7" instead of "if i * i == 49" gives half runtime on my box. This is a bit surprising as multiply is considered very fast generally. Nim Compiler Version 0.18.0 [Linux: amd64]
Re: question about templates / namespaces / modules
Have you tried something like when AVX2_Available(): Of course that can only work when your AVX2_Available() is known at compile time...
Re: Get base object from inherited object.
Calling getType() multiple times may give you the parents, I did that here: [https://github.com/StefanSalewski/gintro/blob/master/gintro/gimpl.nim#L12](https://github.com/StefanSalewski/gintro/blob/master/gintro/gimpl.nim#L12) I got it from a hint of Araq, I have no idea what really is happening.
Re: Though about identifiers in text editors.
> Why not calling Nimsuggest on space hits and carriage returns only ? Yes this is one solution, but I was not really happy with it. In the general case one single keystroke can change highlight of the whole file. For example when we modify a var or type definition all occurrences of that var or type in that file can become invalid, and I think highlight should show that immediately. So only cursor movements are keystrokes which for sure do not need a new nimsuggest query. And if I remember correctly nimsuggest does send for each query the information for the whole file, which is a lot traffic and CPU load.
Re: Question about arrangement of source files with modules
Yes, nimsuggest works really not bad now. For example I can investigate tables.nim fine, jumping to impl works also. One problem are still the generic procs, that symbols seems to be inactive, I guess there is already an hard issue in bug tracker. Now I consider supporting the outline and highlight commands also. Seems that these send always info for the full file, which can be some thousand lines. And format for both commands is very different currently: highlight skConst 11088 5 highlight skConst 11235 12 > outline engine.nim:engine.nim:120:0 outline skVar engine.ENDG /home/stefan/nim-chess2/engine.nim 13 4 "" 100 outline skProc engine.deleteIf /home/stefan/nim-chess2/engine.nim 15 5 "" 100 Testing should be easy, so maybe I will do. But processing thousand of lines for each keystroke may be a bit slow
Re: GTK 3.20 Nim wrapper
> I'm confused in all that pointer-reference-object_itself stuff I have already downloaded the source code of librsvg-2.40.16. Seems to be really a tiny lib, and the c headers contains not many strange macros, so building the wrapper should be easy. (There are bitfields used, but fortunately latest c2nim supports that :) I do not understand that lib well, so testing will be some work. For example I still wonder about your mentioned rsvg_handle_close (). From the API documentation: "Closes handle , to indicate that loading the image is complete. This will return TRUE if the loader closed successfully. Note that handle isn't freed until g_object_unref is called.". No idea currently. I think the wrapper will be finished in a few days, but maybe I will just ignore testing.
Re: Basic pointer question
OK, I think I see your problem. In Nim an empty subscript [] notation can be used to derefer a reference or ptr. So if p is a pointer to string, in C++ you would write '*'p to dereference it, but in Nim you write p[]. And in Nim you can write p[n] to access the n'th character in that string. I would guess that p[][n] == p[n] but I have never tried if that compiles. In C++ we could write ('*'p)[0] to access the first character, in Nim that is p[0]. That is easier to write, and I think that implies no restrictions, as we do no pointer arithmetic in Nim like p++ in C. Note: I put wrong '' around the star to make forum work...
Why does this not compile, and how can I fix it?
import strutils type App = ref object of RootObj i: int proc isDigit(app: App) = discard macro xconnect(widget: RootRef; signal: string; p: typed; arg: typed; ignoreArg: bool): untyped = discard proc main = let app: App = nil xconnect(app, "activate", isDigit, "", true) main() # # nim -v # Nim Compiler Version 0.17.2 (2017-09-08) [Linux: amd64] # Copyright (c) 2006-2017 by Andreas Rumpf # $ nim c button.nim # button.nim(15, 11) Error: type mismatch: got (App, string, proc (app: App){.noSideEffect, gcsafe, locks: 0.} | proc (c: char): bool{.noSideEffect, gcsafe, locks: 0.} | proc (s: string): bool{.noSideEffect, gcsafe, locks: 0.}, string, bool) # but expected one of: # macro xconnect(widget: RootRef; signal: string; p: typed; arg: typed; ignoreArg: bool): untyped
Re: Subtle memory management error found
> Can you show me how to do that? When you are using the Nim compiler from the command line, then in the current working directory a subdirectory with name nimcache is created. For example "nim c test.nim" creates "nimcache/test.c". You can inspect that intermediate C code. When you have clang installed, you may try "nim c --cc:clang myprog.nim" to use the clang compiler. Or try compiling with and without option "-d:release" to see if it makes a difference. Other C compiler options you may specify in the global or local nim.cfg file. For example I generally use in my working directory something like path:"$projectdir" nimcache:"/tmp/$projectdir" gcc.options.speed = "-march=native -O3 -flto -fstrict-aliasing" fstrict-aliasing may not work properly as Mr R. Behrends recently told us, so use better -fno-strict-aliasing which is the default. -flto is link time optimazion, it gives smaller executables generally. -O3 is highest gcc optimazion, you may try -O0, -O1, -O2 also. And also without -march=native. Do you have a recent, but not too new gcc version?
Re: compiler error in 0.18.0 ??
jzakiya, you may wonder why your program eats that much memory. I had just looked at you code, and tried this: #for byt in seg[0..Kn-1]: # count the twin primes in the segment # primecnt += uint(pbits[byt]) # count the '0' bit pairs as twin primes for jj in 0 .. Kn-1: # count the twin primes in the segment primecnt += uint(pbits[seg[jj]]) $ nim c --cc:gcc --d:release --gc:none h.nim $ ./h Enter integer number: 500_000_000_000 segment has 262144 bytes and residues groups prime candidates = 1333; resgroups = 167 create nextp[6x57081] array perform Twin Prime Segmented SoZ last segment = 75435 resgroups; segment slices = 63579 total twins = 986222314; last twin = 4062+/-1 total time = 205.109 secs Seems to work now, so that part of your code seems to generate a copy of the seq for each call.
Re: Dynamic Object Type Fields
> So soemthing like Python's setattr() doesn't exist then? I think when you want support for dynamic runtime attributes, you have to prepare for it in a compiled language. For example you can add a field of type seq or table to your object and a proc for adding data to this field. Of course in a typed language like Nim adding arbitrary data types like ints, strings, objects may not work. If that is necessary you may wrap your attributes in objects, maybe in variant types?
Re: Howto make arbitrary macro parameters persistant (non volatile)
Yes sure, Nim's strings are garbage collected, so GC_ref is available. But the user can pass really arbitrary data, maybe plain ints. Maybe I should just use "when compiles(GC_ref(data))". Maybe not the smartest solution, but should work. Then I only still have to learn how I copy data, I guess something like malloc() and copyMem() is available... Not Sure about deepCopy still.
Re: float64 hash
Hashing floats is not that trivial. A common problem are rounding errors. Do you want/need identical hash for i.e. (3.0 + 4.0) and (7.0)? If yes, then it may be necessary to mask the less significant bits before applying the hash function. So, before choosing a concrete optimal hash function, it may be necessary to consider the range of your numbers. In the simplest case, it may be enough to do some plain mathematical operation on your numbers before hashing to get what you want, maybe just adding always the same constant. [EDIT] and of course, for more information you may ask google, i.e. [http://stackoverflow.com/questions/4238122/hash-function-for-floats](http://stackoverflow.com/questions/4238122/hash-function-for-floats)
Re: What do you think about Redox and Electron?
I heard about Rust OS some months ago (Is there one more than Redox). I think that is very interesting, indeed that would be my main motivation to learn Rust language deeply. But it is very hard for new operating systems to become popular. For Linux it was a bit different, because it was only a Unix clone, so it was not necessary to develop new ideas, and some people where already familiar with Unix. Most other new OS failed. Most critical are device drivers, for which often only closed source drivers exist. Using these may be difficult, and may destroy the benefits of a new, secure OS. And developing other state of the art core components is much work, as Wayland display system, GUI toolkit, OpenGL/Vulkan support or a file system like BtrFs. And all the other Tools -- for Linux we still have no real good CAD or Photoshop, just to name 2. Of course with a good language it is a lot easier and faster, but still take much man power. But maybe Rust OS will get strong support from a very big company or government?
Re: Nim versus Julia benchmark comparison
And can you please try to avoid the ugly cast: #var u:array[4,int64] = cast[array[4,int64]]([60,1,342,0]) var u: array[4, int64] = [60.int64, 1, 342, 0] # should work -- if not tell Araq
Re: Generating a const by a proc -- unexpected result
Thanks. Should I add that example to Nim's github issue tracker?
Re: Fastest way to count number of lines
If speed is really important for you, you may consider SIMD instructions. D. Lemire gave an example for this in his nice blog: [https://lemire.me/blog/2017/02/14/how-fast-can-you-count-lines](https://lemire.me/blog/2017/02/14/how-fast-can-you-count-lines)/
Re: Windows nim binaries freeze
:
GetType() for object type macro parameter
import macros type S = string I = int O = object i: int P = ref O var i: I var s: S var p: P var o: O macro mconnect(arg: typed): typed = let at = getType(arg) echo $(at.toStrLit) if at.len > 1: echo $(at[1].toStrLit) mconnect(s) mconnect(i) mconnect(p) mconnect(o) Output is Hint: macros [Processing] string int ref[O] O object i How can I get P instead of ref[O] and O instead of object i ? I need that for a cast in gtk connect macro. (I think I may get what I need when I use type() outside of the macro and pass the result as an additional parameter to the macro. But I had the feeling that getType() can do it also?)
Re: Help with parallelizing a loop
Indeed Jack, I think sync() is nonsense when parallel statement is used.
Re: Nim in Action is now available!
> IMO your rewording of the explanation of forward declaration also leaves > something to be desired. Yes, it is difficult to explain, for me, in english. I just tried, as only complaining is sometime too easy. For the forward declaration, I think there is already a secret pragma to make it unnecessary, I once tried it, was working, but have never really used it. Relaxing forward declarations was mentioned a few times, some people would really love it. Recently someone in IRC talked about new problems when forward declarations would be relaxed, I think it was related to templates or macros and their order
Re: Shift operation for array elements
@OderWat Sorry, can not really understand... Somethink like memCopy or memMove? That was my first idea, but I was very unsure what would happen when array elements are not somethink like plain ints, but objects with refs. Would that confuse the GC? And of course one may ask if array shifting is a good idea at all -- for many use cases other data structures may be a better solution. I was in need for that shifting for may chess game -- there position in the array is bound to ply, use of array is very convenient and overhead is very low. I can not remember if i inspected Nim sources before i started coding the shift proc -- I think so, but coding time was some months ago. I guess for seqs there may exist a deleteAt() which we may inspect.
Re: Strings and C.
It is generally a bad idea to send the whole seq to C function because there may reside additional data like seq length at start of memory chunk. Try to use address of first element of the sequence instead.
My first nimble package
stefan@nuc ~/gintro $ ls -lt total 40 drwxr-xr-x 1 stefan stefan 210 Jul 7 00:31 gintro -rw-r--r-- 1 stefan stefan 2288 Jul 7 00:30 gintro.nimble drwxr-xr-x 1 stefan stefan48 Jul 6 17:32 tests drwxr-xr-x 1 stefan stefan94 Jul 6 15:27 examples -rw-r--r-- 1 stefan stefan 113 Jul 6 15:27 nim.cfg -rw-r--r-- 1 stefan stefan 25629 Jul 6 15:27 README.adoc -rw-r--r-- 1 stefan stefan 1071 Jul 6 15:26 LICENSE stefan@nuc ~/gintro $ cat gintro.nimble # Package version = "0.1.0" author= "Stefan Salewski" description = "High level GObject-Introspection based GTK3 bindings" license = "MIT" skipDirs = @["examples", "tests"] # Dependencies requires "nim >= 0.17.0" import ospaths #mode = Whatif proc prep = let this = thisDir() let td = getTempDir() cd(td) let wd = "gintrosalewski" mkDir(wd) cd(wd) mkDir("ngtk3") cd("ngtk3") exec("git clone https://github.com/ngtk3/nim-gdk_pixbuf;) exec("git clone https://github.com/ngtk3/common;) exec("git clone https://github.com/ngtk3/nim-atk;) exec("git clone https://github.com/ngtk3/nim-cairo;) exec("git clone https://github.com/ngtk3/nim-gdk3;) exec("git clone https://github.com/ngtk3/nim-gio;) exec("git clone https://github.com/ngtk3/nim-glib;) exec("git clone https://github.com/ngtk3/nim-gobject;) exec("git clone https://github.com/ngtk3/nim-gtk3;) exec("git clone https://github.com/ngtk3/nim-pango;) exec("git clone https://github.com/ngtk3/nim-gir;) exec("ls -lt") exec("ls -lt " & this) echo this echo(this / "tests" / "gen.nim") cpFile(this / "tests" / "gen.nim", td / wd / "gen.nim") cpFile(this / "tests" / "combinatorics.nim", td / wd / "combinatorics.nim") #mkDir("nim_gi") cpFile("nim-gio/src/gio.nim", td / wd / "gio.nim") cpFile("nim-atk/src/atk.nim", td / wd / "atk.nim") cpFile("nim-glib/src/glib.nim", td / wd / "glib.nim") cpFile("nim-gdk3/src/gdk3.nim", td / wd / "gdk3.nim") cpFile("nim-gtk3/src/gtk3.nim", td / wd / "gtk3.nim") cpFile("nim-gobject/src/gobject.nim", td / wd / "gobject.nim") cpFile("nim-cairo/src/cairo.nim", td / wd / "cairo.nim") cpFile("nim-cairo/src/cairo_pragma.nim", td / wd / "cairo_pragma.nim") cpFile("nim-pango/src/pango.nim", td / wd / "pango.nim") cpFile("nim-pango/src/pango_cairo.nim", td / wd / "pango_cairo.nim") cpFile("nim-gdk_pixbuf/src/gdk_pixbuf.nim", td / wd / "gdk_pixbuf.nim") cpFile("nim-gir/src/gir.nim", td / wd / "gir.nim") cd(td) cd(wd) exec("nim c gen.nim") mkDir("nim_gi") exec(td / wd / "gen") let mods = listFiles("nim_gi") for i in mods: let j = i[7 .. ^1] echo j cpFile(i, this / "gintro" / j) task prepair, "prepairing gintro": #before install: echo "prepairing gintro" prep() Well, not yet pushed to github, but when I execute nimble in the gintro directory it does indeed work. If you don't know what it is: It is nimble install for [https://github.com/StefanSalewski/nim-gi](https://github.com/StefanSalewski/nim-gi) with new name gintro suggested by Araq. But a few questions remain: Currently I have to type "nimble prepair" followed by "nimble install". I guess some users may prefer to type only "nimble install". So I tried the before install hook. but that does not work, the hook seems to be not executed. What "nimble prepair" does: It generates all the modules like gtk.nim, glib.nim, pango.nim ... into the gintro directory. That dir is initially empty. If that is done, then "nimble install" installs that files into ~/.nimble/pkgs/gintro-0.1.0/gintro That is fine, and after that I can place my applications everywhere, use imports like gintro/gtk and I can compile them. Great. Next question: mode = Whatif as mentioned in nimscript module would make debugging easier, but I got it not working, Whatif symbol was undefined. Next: In ~/.nimble/pkgs/gintro-0.1.0/gintro I get all the generated modules, and that modules partly import each other. Currently the modules still use plain import, for example gtk.nim uses import glib, gobject. Seems still to work. Should I fix that to import gintro/glib, gintro/gobject? Next: What shall I do with the example files from the tutorial in examples directory? Next: listFiles() seems to give not plain file names, but directory prefix, which is difficult to remove. Is there a better way. Well, the dependency check for gtk developer files are still missing, I will add that tomorrow. And some more checks and cleanup when possible.
Re: int literals and if statement
Kerp, you are working on the Vulkan bindings? Great! For C flags you should strongly consider using Nim's sets! I did that for the high level GTK bindings recently. Have code like type RegionFlag* {.size: sizeof(cint), pure.} = enum even = 1 odd = 2 first = 3 last = 4 only = 5 sorted = 6 RegionFlags* {.size: sizeof(cint).} = set[RegionFlag] So you can pass procs sets as parameter. The empty set {}, or something like {RegionFlags.sorted, RegionFlags.even}. It is not a very compact notation for pure Enums unfortunately. I hope this will work fine for GTK, have not yet tested. Of course that needs some mangling, flagNone=0 is generally removed, first=8 becomes first=3. Another solution is using distinc ints. Or enums, but than you have to define some operations.
Re: Tabulation symbols not allowed
> The big problem I've had with tabs was in team programming, But there is no problem, as long as tabs and spaces are not mixed for indentation purpose in a single file. And no one wants to allow mixing. There is one big advantage of tabs: Indent width can be freely configured, without the need to modify the source code itself. And spaces can be very tiny for some proportional fonts, so that the default 2 spaces per indent step are too small, so I use 3 or four spaces per step, which is again large for people with other fonts. Forbidding tabs is a very strong restriction for our freedom. But there is one reason why I am currently willing to accept it -- github makes tabs equal to 8 spaces, so for github hosted files I would have to replace my tabs to spaces anyway.
Error: illegal capture 'a' -- I have no idea what that means
import random, algorithm # a < b ==> cmp(a, b) < 0 proc cmp(a, b: int): int = (a > b).int - (a < b).int proc quicksort(a: var openarray[int]; left, right: int; cp: proc (a, b: int): int) = proc qsort(left, right: int) = var l, r, p: int let len = right - left let len2 = len div 2 if true: # insertion sort on tiny array for i in left + 1 .. right: for j in countdown(i, left + 1): if cp(a[j], a[j - 1]) >= 0: break # this is the line with error swap(a[j], a[j - 1]) return qsort(a.low, a.high) var x: array[2e6.int, int] quicksort(x, x.low, x.high, cmp) e.nim(15, 17) Error: illegal capture 'a I tried writing it in this way because recursively passing the cmp proc makes sorting a bit slower. I tried pragmas procvar and closure, but that seems to make no difference.
Seq with custom fields
I think I have still not really learned that. I think I may write something like type ExtSeq = object s: seq[int] timestamp: string var es: ExtSeq # init es.s.add(7) echo es.s[0] echo es.timestamp But I would like to just write es.add(7) echo es[0] Of course I have ideas how to do it. I may define customs procs or maybe templates. But I am not sure what is the best solution or where I can find an example...
Re: cannot countProcessor in compile time
> If you really need to know the number of processors on a system, you could > always compile a sub-program during compile-time and invoke it. Indeed I assumed that. But I have no idea how to do it in detail in a user friendly way -- so that user can still do a plain "nimble install myTool". Note that this is not limited to number of CPUs, we may be interested in available ram, GL version, GPU and much more at compile time.
Re: Is this a compiler bug?
I would have expected that the compiler sees that the proc parameter does not match and so ignores that proc and assumes that a type conversion is intended.
Re: GTK 3.20 Nim wrapper
> @Stefan_Salewski, seems that RsvgHandle has not svg data it's nil instead Of course making such a gtk related wrapper is not fully trivial. I think I once said that RSVG is not a very big library, so it should not be too much work to make the wrapper. Unfortunately I have never used RSVG myself, so I would have to read about it first a bit, so that I can do at least some minimal testing. So for me I assume it would be about one week fulltime. May be justified when people really need it.
Can var proc parameters be faster than function results?
Of course for plain compilers var parameters can be faster, because without smart optimizations result objects can be first allocated on the proc stack and then copied back to the caller variable. But I had the strong feeling that this optimization is generally done, so I never tried to avoiding result parameters. But my current observation is that a var parameter can be indeed faster, by 10 to 20 % in my test case. (I discovered that fact by tuning my chess engine, so it is a real life observation...) import random, times type Data = tuple a: array[16, int] age: int proc p1(): Data = for i in mitems(result.a): i = random(7) result.age = random(7) proc p2(res: var Data) = for i in mitems(res.a): i = random(7) res.age = random(7) proc main = var h: Data var sum: int var t: float # cpuTime() t = cpuTime() for x in 0 .. : h = p1() sum += h.age echo sum echo "p1: ", cpuTime() - t t = cpuTime() for x in 0 .. : p2(h) sum += h.age echo sum echo "p2: ", cpuTime() - t main() # $ nim c -d:release ups.nim # ~/nim-chess2 $ ./ups # 29915 # p1: 0.000519 # 60011 # p2: 0.00042
Re: Blog post about Nim performance tuning
Nice -- I already saw it some days ago. Will read it carefully soon...
Re: Why takes this code 22ns with cstring and 52ns with string?
Indeed -- putting all that test code in a proc make differences disappear! I am aware of performance problems of code outside of procs, but I really had not thought that that was the problem in this case. And I had not assumed that it makes 30 ns difference for a proc call. I think in future I really should avoid global code even for small tests.
Re: My first nimble package
Well, this is the cleaned up version. We do check for dev packages on ubuntu, check if tmp dir already exists and delete tmp dir when done. Problem with mode = Whatif was that Whatif is a pure enum, issue is posted. The modules still import each other directly, without the gintro prefix. Seems to work fine, I hope that is indeed intended and desired. I can install my local package fine with "nimble prepare", "nimble install". From bug [https://github.com/nim-lang/nimble/issues/280](https://github.com/nim-lang/nimble/issues/280) I think I can not avoid that nimble prepare. But I am still not sure if "nimble prepare" will work for remote packages at all! $ cat gintro.nimble # Package version = "0.1.0" author= "Stefan Salewski" description = "High level GObject-Introspection based GTK3 bindings" license = "MIT" skipDirs = @["tests"] # Dependencies requires "nim >= 0.17.0" when defined(nimdistros): import distros if detectOs(Ubuntu) or detectOs(Debian): foreignDep "libgtk-3-dev" elif detectOs(Gentoo): foreignDep "gtk+" # can we specify gtk3? #else: we don't know the names for all the other distributions # foreignDep "openssl" import ospaths proc prep = let this = thisDir() let td = getTempDir() cd(td) let wd = "gintrosalewski" if dirExists(wd): quit("gintro: tmp directory already exists!") mkDir(wd) cd(wd) mkDir("ngtk3") cd("ngtk3") exec("git clone https://github.com/ngtk3/nim-gdk_pixbuf;) exec("git clone https://github.com/ngtk3/common;) exec("git clone https://github.com/ngtk3/nim-atk;) exec("git clone https://github.com/ngtk3/nim-cairo;) exec("git clone https://github.com/ngtk3/nim-gdk3;) exec("git clone https://github.com/ngtk3/nim-gio;) exec("git clone https://github.com/ngtk3/nim-glib;) exec("git clone https://github.com/ngtk3/nim-gobject;) exec("git clone https://github.com/ngtk3/nim-gtk3;) exec("git clone https://github.com/ngtk3/nim-pango;) exec("git clone https://github.com/ngtk3/nim-gir;) cpFile(this / "tests" / "gen.nim", td / wd / "gen.nim") cpFile(this / "tests" / "combinatorics.nim", td / wd / "combinatorics.nim") cpFile("nim-gio/src/gio.nim", td / wd / "gio.nim") cpFile("nim-atk/src/atk.nim", td / wd / "atk.nim") cpFile("nim-glib/src/glib.nim", td / wd / "glib.nim") cpFile("nim-gdk3/src/gdk3.nim", td / wd / "gdk3.nim") cpFile("nim-gtk3/src/gtk3.nim", td / wd / "gtk3.nim") cpFile("nim-gobject/src/gobject.nim", td / wd / "gobject.nim") cpFile("nim-cairo/src/cairo.nim", td / wd / "cairo.nim") cpFile("nim-cairo/src/cairo_pragma.nim", td / wd / "cairo_pragma.nim") cpFile("nim-pango/src/pango.nim", td / wd / "pango.nim") cpFile("nim-pango/src/pango_cairo.nim", td / wd / "pango_cairo.nim") cpFile("nim-gdk_pixbuf/src/gdk_pixbuf.nim", td / wd / "gdk_pixbuf.nim") cpFile("nim-gir/src/gir.nim", td / wd / "gir.nim") cd(td) cd(wd) exec("nim c gen.nim") mkDir("nim_gi") exec(td / wd / "gen") let mods = listFiles("nim_gi") for i in mods: let j = i[7 .. ^1] cpFile(i, this / "gintro" / j) cd(td) rmDir(wd) # cleanup task prepare, "preparing gintro": #before install: echo "preparing gintro" prep()
Re: Surprises with Generics
Reading this blog post [http://nibblestew.blogspot.de/2017/11/aiming-for-c-sorting-speed-with-plain-c.html](http://nibblestew.blogspot.de/2017/11/aiming-for-c-sorting-speed-with-plain-c.html) > I just remembered a discussion some time ago: S. Salewski wrote: > A consequence may be, that for algorithm.sort() we do not need a cmp() proc > parameter (which can not be inlined and is a bit slow so). We may just define > a plain cmp() proc in our module for the types which we pass to compare? > > Some months ago I tested a quicksort proc, and found out that giving a cmp() > proc for custom types decreases performance by about 25 percent compared to > using a default cmp proc for known standard types. So maybe we should provide indeed a sort proc without cmp() function.
Re: Why is integer multiplication so slow here?
Hlaaftana, thanks for confirming. I was really tired yesterday and though I was doing something wrong. cdome, your message makes not too much sense for me currently. Indeed I tried using unlikely() for this test, which made no difference, as expected, as automatic branch prediction should work fine here. Indeed I wonder if Nim supports branchless cmov instructions at all currently, maybe not because of so much goto use? At least I have not seen a cmov in Nims assembler listings yet. My feeling is, that mul is indeed slow in this special loop -- will inspect assembly listing when I have some more time.
Re: pixbuf_new_from_stock
What do you think where the problem is? Are you following a C example or the Krause book? As you know I am using only GTK3 -- but from my memory of examples and the Krause book I think that the second parameter of gtk_image_new_from_stock is generally a C enum of type GtkIconSize. So allowed values may be 0,1,2... and the absolute size value 32 may be invalid. Well just a guess, I have not the gtk2 sources or the gtk2 nim wrapper available currently. For your last question, the number (5319) is the process id, so it contains no information of error location. GTK developers generally compile whole GTK (and maybe other libs too) with debugger support, and then seems to be able to find error locations with gdb. I tried that once to find the reason for a gtk warning, but was not really successful. Generally it is easier to write just correct code, so you need no low level debugging.
Re: register pragma
Have you tried something like var mycounter {.register.} = 0 You can check the C sources if it is applied, but as the manual says, in nearly all cases the (C) compiler knows better.
Re: Nim Chess 2 with transposition table support is available
Version 3 is now available! [https://github.com/StefanSalewski/nim-chess3](https://github.com/StefanSalewski/nim-chess3) Ram usage is reduced to about 340 MB, and I tried some other improvements. Not much tested yet. Nimble install is still not possible, but for Linux a copy and past of the provided instruction followed by a "bash thisScript" works. The old versions are still available at [https://github.com/ngtk3](https://github.com/ngtk3).
Re: TaintedString.parseInt problem
Why not use echo to see the content of the string you pass to parseInt? Note: for bash command expr / indicates integer division. For Nim / is floating point division, you may use div for integer division, or you may round the floating point result. So may guess is that you pass a floating point number to parseInt, which it may not like.
Re: GTK 3.20 Nim wrapper
No not as a library. But I have not investigated the remaining crashes. I worked on it two months ago for the last time and used the editor then while working on the chess game. For me some crashes are no problem, I saved every ten minutes. And I think there are no other users beside me. One reason why I have not done further investigations was that there are still some bugs open in nimsuggest bug tracker, and I wanted not to add more. I think you have more important work to do. When I started with Nim two years ago I had a short look into aporia code -- there all nimsuggest related code was incapsulated deeply in try/except blocks with permannently restarting the nimsuggest process. I was not really happy with that design. My current code has no try/except and no restart of nimsuggest. For some problems I know why they occur, I have reported a few at nimsuggest bug tracker, and can report some more. For the remaining problems I have to do some investigations. Some problems my be GTK related, fixing these should be easy. [https://github.com/ngtk3/NEd](https://github.com/ngtk3/NEd)
Re: Using cstringArray and allocCstringArray
> but allocCstringArray wants a openarray of string. So you should give it one. You should know how you can create an array or a seq of strings. When you know that 256 chars are desired for each string, then you fill the array with strings with at least this size. And finally you pass that array or seg to allocCstringArray().
Fast branchless sign() function
[http://stackoverflow.com/questions/14579920/fast-sign-of-integer-in-c](http://forum.nim-lang.org///stackoverflow.com/questions/14579920/fast-sign-of-integer-in-c) I would like to have a sign function in std lib. I was really surprised that the brachless variant makes such a difference -- I had expected nearly no difference because result dominated by random() function, or due to identical assembler code of gcc 5.4.0. import random #proc sign(x: int): int = # if (x > 0): return 1 # elif (x < 0): return -1 # else: return 0 proc sign(x: int): int = (x > 0).int - (x < 0).int #proc sign(x: float): int = # if (x > 0): return 1 # elif (x < 0): return -1 # else: return 0 proc sign(x: float): int = (x > 0).int - (x < 0).int var j = 0 for i in 0 .. 1e7.int: j += sign(random(7).float - 3.0) echo j j = 0 for i in 0 .. 1e7.int: j += sign(random(7) - 3) echo j stefan@nuc ~/sign $ nim c -d:release s.nim stefan@nuc ~/sign $ time ./s -2839 855 real0m0.314s user0m0.312s sys 0m0.000s stefan@nuc ~/sign $ nim c -d:release s.nim stefan@nuc ~/sign $ time ./s -2839 855 real0m0.188s user0m0.188s sys 0m0.000s
Re: GTK 3.20 Nim wrapper
The plain Nim GTK3 editor is now available in version 0.2 [https://github.com/ngtk3/NEd](https://github.com/ngtk3/NEd) I have added multiview support, fixed the GTK related modules and added a short Asciidoc Readme. Not really tested yet. You should be able to compile it at least on 64 bit Linux systems. Nimsuggest is still fragile and can generate crashes. Working with multiple files at the same time seems to be a problem. Maybe we have indeed to restart mimsuggest when we switch files? And suggestions do not work reliable yet.
Re: Howto make arbitrary macro parameters persistant (non volatile)
Araq, the deepCopy() part works fine with string and int parameters, but unfortunately not with objects. I got it working, when I substitute at by "ParObj" literal everywhere: (Of course that makes no sense for general use case) type ParObj = object x: float proc clicked(button: XButton; arg: ParObj) = echo arg.x echo button.x macro connect(widget: Widget; signal: string; p: untyped; arg: typed): typed = inc(ProcID) let wt = getType(widget) # widget type let at = getType(arg) # argument type let signalName = ($signal).replace("-", "_") # maybe we should just use plain proc names let procNameCdecl = newIdentNode("connect_for_signal_cdecl_" & signalName & $ProcID) let procName = newIdentNode("connect_for_signal_" & signalName & $ProcID) let scName = newIdentNode("sc" & signalName) result = quote do: proc `procNameCdecl`(button: ptr Object00 , data: pointer) {.cdecl.} = var h: pointer = g_object_get_qdata(button, Quark) `p`(cast[`wt`](h), cast[ParObj](data)) #`p`(cast[`wt`](h), cast[`at`](data)) proc `procName`(self: `wt`; p: proc (self: `wt`, arg: ParObj); a: ParObj) = when false:#compiles(GC_ref(a)): GC_ref(a) `scName`(self, `procNameCdecl`, cast[pointer](a)) else: #var ar: ref `at` var ar: ref ParObj new(ar) deepCopy(ar[], a) `scName`(self, `procNameCdecl`, cast[pointer](ar[])) `procName`(`widget`, `p`, `arg`) connect(button1, "clicked", clicked, parObj) So "let at = getType(arg)" in macro and using at is not identical to ParObj. While for base types int and strings it works. I have the feeling that getType() gives only plain object type. Is there a way to get real object type, which is ParObj here?
Re: Big integer litterals
@lscrd Nim 0.18 is correct indeed -- see language manual: Pre-defined integer types These integer types are pre-defined: int the generic signed integer type; its size is platform dependent and has the same size as a pointer. This type should be used in general. An integer literal that has no type suffix is of this type if it is in the range low(int32)..high(int32) otherwise the literal's type is int64.
Re: Bug (?) with templates
template bar() = echo a template foo() {.dirty.} = let a = 5 bar() foo() echo a I would expect exactly that behaviour. As templates a hygienic by default, we need dirty pragma for foo() to make variable visible outside.
Re: Nim vs D
> Without main function: 5.004 s With main function: 3.126 s That is really some magic which we should investigate, document and remember.
Re: GTK 3.20 Nim wrapper
> Yes, a couple of fixes and it worked. If you want I'll write more detailed. Yes, would be fine. Araq just told me that he regards proc names like int32 invalid -- they shadow type conversions. So I have to filter all the GTK3 related modules for proc names which may conflict with type names. Will take some time... My ned editor -- well there are some bugs still. For example currently it works only when started from its directory. Otherwise the gsettings configuration are not found. For Linux one solution is this: # And for making gsettings available system wide one method is, as root # https://developer.gnome.org/gio/stable/glib-compile-schemas.html # echo $XDG_DATA_DIRS # /usr/share/gnome:/usr/local/share:/usr/share:/usr/share/gdm # cd /usr/local/share/glib-2.0/schemas # cp org.gtk.ned.gschema.xml . # glib-compile-schemas . I would prefer a solution which needs no root access, and I have no idea how to do that on Windows. I will ask at the gtk mailing list, but do not expect to get an answer.
Re: Will Nim in Action also be printed in colorful?
The paper version was announced as "printed in black & white". [https://manning.com/books/nim-in-action?a_aid=niminaction_bid=78a27e81](https://manning.com/books/nim-in-action?a_aid=niminaction_bid=78a27e81) But the ebub and PDF version has color and looks nice. There is no reason to buy paper in these days (if the book is not about string theory, quantum mechanics or compiler construction) -- better buy electronic version without discount, maybe one more for a friend, and support bounty source. My opinion.
Creating a new seq is not that fast
Of course not, there is much allocation work involved. But about 500 ns (a few thousand CPU cycles) is indeed more as my expectations. I discovered that when tuning my chess engine -- using one more tiny seq noticeable reduced performance. Of course seq's are convenient, because of existing add() operation. A plain array allocated on the stack is faster, fixed size is OK, because I have to store only the moves or captures for current position, but I would have to track current add position. Chess is recursive, so I can not use one single global seq. My current idea is to use a global seq as as first buffer for collecting captures, and only swap() that buffer with a new allocated seq when it turns out that there are possible captures at all available. (I guess swap will not copy data, but only pointers, so it may be fast) Or I may use my own defined container which is allocated on the stack. For that case I would have to define my own add() and sort() operations. I don't think that I will get trouble with stack size... import times, random type MyBuffer = tuple d: array[128, int] len: int proc test(): int = var s = newSeqOfCap[int](128) s.len proc tx(): int = var s: MyBuffer s.len proc t0(): int = random(7) proc main = var t: float # cpuTime() var i: int t = cpuTime() i = test() i = test() i = test() i = test() i = test() i = test() i = test() i = test() i = test() i = test() echo "10 * test: ", cpuTime() - t t = cpuTime() i = tx() i = tx() i = tx() i = tx() i = tx() i = tx() i = tx() i = tx() i = tx() i = tx() echo "10 * tx: ", cpuTime() - t t = cpuTime() i = t0() i = t0() i = t0() i = t0() i = t0() i = t0() i = t0() i = t0() i = t0() i = t0() echo "10 * t0: ", cpuTime() - t main() # nim c -d:release t.nim # 10 * test: 5.013e-06 # 10 * tx: 0.0 # 10 * t0: 0.0
Re: Total noob, statically allocated circular buffer on microcontroller question
> running Nim code on a medium size MSP430 32K Flash, 4K RAM. The > MSP430F5510-STK board from Olimex. Interesting. Can you access all the registers already? Do you use GC? Your project based on [https://github.com/lonetech/nim-msp430](https://github.com/lonetech/nim-msp430) ? Circular buffer should be your smallest problem I guess Note, Dom's book has no microcontroller chapter, it is more intended for PC programming.
Re: compile time code execution problem
> Coming from Ruby/Elixir, Maybe some C exercises would help Note that modpg.unit and rescnt.uint are not plain casts (reinterpretation of bit pattern) but type conversions. Type conversions may ensure that the values are not negative before conversion and raise exceptions otherwise. I don't know if -d:release will turn of that check. And when you use a type conversion, then the compiler can not work with real constant values any longer, which may degrade performance. If you are sure that conversion is valid, you may use a plain cast like cast[uint](modpg). But why are you not using uint from the beginning for your constants if you desire uints? I would assume that this compiles. const modpg= parameters[0].uint Well, that will not work for the seq. Maybe try to fix the proc signature to this: proc genPGparameters(prime: int): (uint, uint, uint, seq[uint]) =
Re: Fun with rdtsc() microbenchmarks
Well, more meaningful and even more funny is this code with random numbers, where the compilers really can not remove the proc calls: import random proc rdtsc(): int64 = var hi, lo: uint32 asm """ rdtsc :"=a"(`lo`), "=d"(`hi`) """ result = int64(lo) or (int64(hi) shl 32) proc sort1(d: var openarray[int]) {.inline.} = template SWAP(x, y: int) = let a = min(d[x], d[y]) let b = max(d[x], d[y]) d[x] = a d[y] = b SWAP(1, 2) SWAP(4, 5) SWAP(0, 2) SWAP(3, 5) SWAP(0, 1) SWAP(3, 4) SWAP(1, 4) SWAP(0, 3) SWAP(2, 5) SWAP(1, 3) SWAP(2, 4) SWAP(2, 3) proc sort2(d: var openarray[int]) = template SWAP(x, y: int) = if d[x] > d[y]: swap(d[x], d[y]) SWAP(1, 2) SWAP(4, 5) SWAP(0, 2) SWAP(3, 5) SWAP(0, 1) SWAP(3, 4) SWAP(1, 4) SWAP(0, 3) SWAP(2, 5) SWAP(1, 3) SWAP(2, 4) SWAP(2, 3) proc testIt = var a = [0,1,2,3,4,5] var b = [5,4,3,2,1,0] var x: array [6, int] var now, start: int64 for i in 0 .. 5: x[i] = random(6) start = rdtsc() sort1(x) now = rdtsc() echo(repr(x)) echo "Cycles: " & $(now - start) for i in 0 .. 5: x[i] = random(6) start = rdtsc() sort1(x) now = rdtsc() echo(repr(x)) echo "Cycles: " & $(now - start) for i in 0 .. 5: x[i] = random(6) start = rdtsc() sort2(x) now = rdtsc() echo(repr(x)) echo "Cycles: " & $(now - start) for i in 0 .. 5: x[i] = random(6) start = rdtsc() sort2(x) now = rdtsc() echo(repr(x)) echo "Cycles: " & $(now - start) when isMainModule: testIt() [0, 2, 2, 5, 5, 5] Cycles: 36 [0, 0, 2, 2, 4, 5] Cycles: 36 [0, 2, 2, 3, 4, 4] Cycles: 140 [0, 0, 0, 3, 3, 5] Cycles: 164
Re: Nim GC Performance
@Varriount Is your conclusion really fair? The Go benchmark seems to include no special tweaking. Araqs version switched of cycle detection. That may be fine for this small example. But when I have a real word complex program, can I be sure that I can switch of cycle detection? For all my tests with cycle detection enabled I got pause times of about 8ms, which is similar to that what Dom got and what Go offer.
Re: Big integer litterals
That is an interesting topic. When you try var x: int = 10 * 1_000_000_000 it seems to compile fine on a 64 bit Linux box. So problem is the constant itself. But what I really ask myself: How does var x = 10 * 1_000_000_000 behave on 32 and 64 bit OS. Is x int or int64. What GTK3 are you using? I guess it will be one of my bindings, but is it oldGTK3 or gintro? And on Linux, Mac or Windows?
Is for procs only one generic parameter allowed?
I tried to create a generic RTree. Beginning was easy, tests of union() and intersect() was working fine. But I did not got search() working -- it gets a rtree parameter and a box, which both are generic. I tried with proc p() which compiles when one of the parameters is used, but not when both are present. I have to admit that such a generic RTree is really hard for the compiler. Maybe I should use a non generic search box (with fixed high enough dimension) for search proc. # http://www-db.deis.unibo.it/courses/SI-LS/papers/Gut84.pdf # RT: range type like float, int # D: Dimension # M: Max entries in one node # LT: leaf type type Dim = static[Natural] Ext[RT] = tuple[a, b: RT] # extend (range) Box[D: Dim; RT] = array[D, Ext[RT]] L[D: Dim; RT, LT] = tuple[b: Box[D, RT]; l: LT] N[D: Dim; RT] = tuple[b: Box[D, RT]; n: N] LA[M, D: Dim; RT, LT] = ref array[M, L[D, RT, LT]] NA[M, D: Dim; RT] = ref array[M, N[D, RT]] H[M, D: Dim; RT, LT] = ref object of RootObj parent: H[M, D, RT, LT] Leaf[M, D: Dim; RT, LT] = ref object of H a: LA[M, D, RT, LT] Node[M, D: Dim; RT, LT] = ref object of H a: NA[M, D, RT] RTree[M, D: Dim; RT, LT] = ref object root: H[M, D, RT, LT] proc newRTree[M, D: Dim; RT, LT](): RTree[M, D, RT, LT] = new result var rt = newRTree[50, 2, float, int]() proc union(r1, r2: Box): Box = for i in 0 .. r1.high: result[i]. a = min(r1[i]. a, r2[i]. a) result[i]. b = max(r1[i]. b, r2[i]. b) proc intersect(r1, r2: Box): bool = for i in 0 .. r1.high: if r1[i].b < r2[i].a or r1[i].a > r2[i].b: return false return true proc search[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; b: Box[D, RT]) = #return newSeq[int]() discard proc p(t: RTree; s: Box) = discard var m, n: Box[2, int] m[0].a = 1 m[0].b = 2 m[1].a = 5 m[1].b = 7 n = [(a: 2, b: 3), (a: 3, b: 6)] echo union(m, n) echo intersect(n, m) #search(rt, m) p(rt, m) $ nim c rtree.nim rtree.nim(60, 2) Error: type mismatch: got (RTree[50, 2, system.float, system.int], Box[2, system.int]) but expected one of: proc p(t: RTree; s: Box)
Re: To optimize operation of replacement of lines in the file
Do you want to search for regular expressions or for plain strings? Plain strings should be faster of course.
Re: Problem using
Now in your code there is no spawn at all! For parallel processing, you have to ensure that there are no conflicts when parallel tasks are accessing your data, otherwise the compiler may make copies of the data before, which may make it slow. And for parallel processing a good use of the CPU cache is also important -- many parallel processes will give no speed increase when data is always fetched from slow RAM instead of cache.
Re: progress while binding libxl
> still be Greek for me. Well, the when statement is really easy to understand and well explained in the manual, so maybe you should read it again. It is good to understand it. What you may be looking for is a converter, see manual. A converter allows automatic conversion of proc parameter types. So you may define a converter which converts cstrings to cwidestrings, and then whenever there is a proc that needs a cwidestring and you pass it a cstring, then that converter is called automatically and does the needed conversion. Note, that use of very many converters may make compilation slower, as the compiler has much effort to select all the right converters. For your code example proc s(val: string|Widecstring): Widecstring = when not type(val) is Widecstring: return newWideCString(convert(val, "utf8", "gb2312")) else: return val I am not sure if that shape make much sense. As Nim is statically typed, a proc signature like "proc s(val: string|Widecstring): Widecstring =" generates two procs, one with string, the other with Widecstring argument. Due to the when statement, the later really does nothing. What you may want here is just a proc or converter that converts from string to WideCString or whatever.
Re: Howto make arbitrary macro parameters persistant (non volatile)
Well, I have a working solution. I can pass a string, an int, and object from the stack to the callback and it works. (Removing a button and reinserting does not work currently, but that is a different problem.) But I still wonder why I have to use the strange name(type(arg)) way to get the type of the callback parameter, and getType(arg) in macro does not work. Of course this code always makes a deep copy of the callback parameter, that wasted some ram. # plain test for high level gi based GTK3 Nim wrapper # https://github.com/StefanSalewski/nim-gi2 import gtk, glib, gobject import macros import strutils import typetraits type ParObj = object x: float type XButton = ref object of Button x: int # TODO: will be moved to library module! let Quark = g_quark_from_static_string("NimGIQuark") # TODO: will be moved to library module! proc initWithArgv*() = var cmdLine{.importc.}: cstringArray cmdCount{.importc.}: cint gtk.gtk_init(cmdCount, cmdLine) proc clicked(button: XButton; arg: ParObj) = echo arg.x echo button.x proc clicked2(button: Button; arg: string) = echo arg proc clicked3(button: Button; arg: int) = echo arg proc bye(w: Window; arg: string) = mainQuit() echo arg var ProcID: int # TODO: this macro will be moved to library module! macro mconnect(widget: Widget; signal: string; p: untyped; arg: typed; rrt: string): typed = inc(ProcID) let wt = getType(widget) # widget type #let at = getType(arg) # argument type let signalName = ($signal).replace("-", "_") # maybe we should just use plain proc names let procNameCdecl = newIdentNode("connect_for_signal_cdecl_" & signalName & $ProcID) let procName = newIdentNode("connect_for_signal_" & signalName & $ProcID) let scName = newIdentNode("sc" & signalName) let at = newIdentNode($rrt) result = quote do: proc `procNameCdecl`(button: ptr Object00 , data: pointer) {.cdecl.} = var h: pointer = g_object_get_qdata(button, Quark) `p`(cast[`wt`](h), cast[`at`](data)) proc `procName`(self: `wt`; p: proc (self: `wt`, arg: `at`); a: `at`) = var ar: ref `at` new(ar) deepCopy(ar[], a) GC_ref(ar) `scName`(self, `procNameCdecl`, cast[pointer](ar[])) `procName`(`widget`, `p`, `arg`) template connect(widget: Widget; signal: string; p: untyped; arg: typed) = mconnect(widget, signal, p, arg, name(type(arg))) proc work = var window: Window = newWindow(WindowType.topLevel) window.setTitle("First Test") window.setBorderWidth(10) var box = newBox(Orientation.vertical, 0) button1: XButton button2 = newButton("Wrapper") button3 = newButton("Int button") parObj: ParObj parObj.x = 3.1415 initButton(button1) button1.setLabel("Nim GI") button1.x = 99 connect(button1, "clicked", clicked, parObj) connect(button3, "clicked", clicked3, 1234567) connect(window, "destroy", bye, "Bye") button2.connect("clicked", (proc(button: Button; arg: string) = echo arg), "Bye") box.add(button1) box.add(button2) box.add(button3) #box.remove(button2) # this does not work currently #box.add(button2) window.add(box) window.showAll let p = button1.getParent assert(p == box) proc main() = initWithArgv() work() GC_fullCollect() gtk.gtkMain() main()
Re: Partial casing is foo_bar
> would like to have a new "alias" functionality Was thinking about it a few times... For example, I have a longer proc with return type View. Can use predefined result variable in the proc, but then I have to remember that result is view. Or I use "var view: View ... return view". alias view result would be one line instead of two. But of course alias can generate confusion if used in the wrong way, so Araq will not like it. (As for my Tabs.) For style: After some thinking, I still have no clear opinion. But my feeling is, that the advantages of partial casing are really not that important (don't have to remember if I have to write filename or fileName) but disadvantages exists due to reduced name space. And of course, some people will not use Nim just because they do not like style insensitivity.
Re: Do we have a RTree or R*Tree for Nim?
Currently I favour to let the shape of the code as it is. One question arise: Would it make sense to rewrite code like this [https://github.com/StefanSalewski/RTree/blob/master/rtree.nim#L305](https://github.com/StefanSalewski/RTree/blob/master/rtree.nim#L305) for j in 1 ..< n.numEntries: if n of Leaf[M, D, RT, LT]: b = union(b, Leaf[M, D, RT, LT](n).a[j].b) elif n of Node[M, D, RT, LT]: b = union(b, Node[M, D, RT, LT](n).a[j].b) else: assert false For max speed into something like this: if n of Leaf[M, D, RT, LT]: let h = Leaf[M, D, RT, LT](n) for j in 1 ..< n.numEntries: b = union(b, h.a[j].b) elif n of Node[M, D, RT, LT]: let h = Node[M, D, RT, LT](n) for j in 1 ..< n.numEntries: b = union(b, h.a[j].b) else: assert false Some languages like Oberon had type guards and the with clause for that, I think it was code like WITH n:Node[M, D, RT, LT] DO or similar, which saves a temporary h pointer. But maybe all that rewriting is unnecessary as the compilers optimize it.
Re: Allocation on heap somehow unstable - Why does this crash?
We had a very similar thread recently: [https://forum.nim-lang.org/t/3054](https://forum.nim-lang.org/t/3054)
Re: How do you install the gtk 3 development libraries and toolchain on Windows 64bit?
> Which directory are your GNOME development libraries themselves installed, I am not using Windows. For gentoo linux, command is just "emerge -av gnome". I can search for directory paths, but I guess that will not really help you for Windows. Personally I would be very interested how well GTK3 works for windows, but I can not really recomment GTK3 for windows users. GTK/Gnome is very death on Linux currently, and I think it is much more death on Windows. The gtk.org page seems to be accessible again (slow) the recommended install for windows users is [http://www.gtk.org/download/windows.php](http://forum.nim-lang.org///www.gtk.org/download/windows.php) "The preferred way to obtain GTK+ and its dependencies in binary form for Windows is to use the MSYS2 project." Please let us know if that works for you.
Re: NEd GTK3 editor is available in v 0.3 now -- with full nimsuggest support
> I tested it, but I did not have any syntax highlighting. I assume on Linux. Do you have syntax highlighting at all, for example in gedit? Do you have syntax highlighting for other files, maybe xml? You may try with another file extension, like ./ned nimdark1.xml but I just discovered that it will crash at program termination with xml. Sorry, will try to fix it soon. Of course, as I wrote in the doc: " Maybe you want to try the included color scheme and syntax highlight XML file? In that case you may consult the gedit instructions. On my Linux box I put these file where the other GtkSourceView files reside: " # as root cp nimdark1.xml /usr/share/gtksourceview-3.0/styles/ cp nim.lang /usr/share/gtksourceview-3.0/language-specs/ For the build script -- yes I will consider that when there should exist people really interested using it. But I heard that VSCode and other editors work fine with Nim, so maybe I will remain the only single user :) (I read the nimble chapter in Dom's book, my impression was that it is really hard to provide a nimble install without conflicting with old GTK2. And unfortunately the gsettings install require root permission, which some people may not really like. I will ask on gtk mailing list is there may be a solution which does not require root, but the lists and IRC are very death currently, and I think as long as there are no real users, the few remaining gtk people will not care.)
Re: Nim versus Julia benchmark comparison
One more explanation for a factor of 3 - 4 in performance can be of course SIMD instructions. Maybe latest Julia is very good in using SIMD? Maybe you can try clang instead of gcc to see if clang can better apply SIMD and related parallel instructions to your code. (Or Julia may pre-compute some of your code?)
Re: GTK 3.20 Nim wrapper
You may try first [https://github.com/ngtk3/nim-chess2](https://github.com/ngtk3/nim-chess2) The readme contains the instructions, which I tested recently with Nim v 0.15.2 on Linux. For Linux you can copy the commands to a file and run the script, bash script.sh. I know that it does not work for OSX, can not help. Of course a nimble install would be more nice, but I can not provide that currently, and I think there are indeed no users.
Re: GUI programming
And of course nimx and QML. And note that latest GTK 3.20 wrapper is at [https://github.com/ngtk3](https://github.com/ngtk3), I will delete the old 3.15 wrapper in the next days...
Re: Nim Dynamic Libraries: exporting functions that return pointer-based types
> I'm trying to create a Ruby extension in Nim, Interesting, maybe you can collect your insights in a blog or forum post. I have used Ruby too in the past, and I wrote some C extensions for using CGAL and Boost library. While I was told that extending Ruby with C was easier than extending Python with C, it was some hard work, mainly due to the CGAL and Boost C++ template stuff and due to Ruby GC. So I am happy that I can do all in Nim now. Well, for Ruby I got the GTK3 bindings for free, and I still may need CGAL and Boost support... To your question, returning Nim strings and using that outside of Nim can not work out of the box. Nim strings are garbage collected, so when there is no longer a reference to a Nim string in the Nim universe, than that string is freed by the GC. (I guess for your array example it is similar.). We have various possibilities to solve that problem. 1. You can call GC.ref() on the returned Nim string, so that CG can not collect it. 2. You can completely turn of GC. 3. You may compile your program without GC support. 4. You may copy the Nim string to a C string by calling alloc() to create a untraced memory location on the heap, copy the string to this location and return that location.
Re: How to debug a compile error in a template?
nim check mycode.nim But it is true, if errors are in code with generics, templates or macros it can occur that there is absolutely no useful hint to the real error location. For example as error position code in system.nim is showed. And some hours ago I had a case with generics where there was shown an WRONG line number for error position.
Re: Proc call is blocking call of finalizer
OK, that is what I guessed more or less... I think I will try to put all the relevant code into another proc and then call GC_fullCollect() when that proc is finished, then all stack of that proc should be released and finalizer should be called for that objects. Will continue testing GTK3 GC behaviour soon...
Re: GUI programming
> Do i have to learn a new GUI language for that programming ? When you have experience in GTK3 programming in C already, you can just start with GTK3 and Nim, it is very similar. You can even convert C GTK3 code to Nim with the tool c2nim, do some modifications, and are done. But to be serious, you told us that you are new to Linux, new to Nim and new to GUI programming. And I guess new to programming at all? So maybe better start with a more traditional language and GUI, maybe Java with its own GUI, or C++ or Python with Qt. Or Windows native GUI, Android GUI, or Mac Swing language. I think for these more detailed tutorials exist. Later you may come back to Nim.
Re: Is it possible to avoid default array initialization?
>From the manual: [https://nim-lang.org/docs/manual.html](https://nim-lang.org/docs/manual.html) The implicit initialization can be avoided for optimization reasons with the noinit pragma: var a {.noInit.}: array [0..1023, char]
Re: Nim in Action is now available!
Well, writing books in a foreign language is not easy... You may have noted that this remark from chapter 2 is still not very nice Order of procedures It is important to note that the order of procedures and procedure calls matters. When calling a procedure, it must be defined above the call site like in the example above. This will likely be changed in a future version of Nim. So I tried for fun to rewrite it. I also mention a proc forward declaration -- I can not remember if you mention it at all: Order of procedure definitions and invocations Before a procedure can be called, the compiler has to be aware of it. That means that it has to be defined in advance -- at a position in the source file above the first use, or in an already imported module. When it is necessary to call a procedure before it can be defined, you may use a forward declaration: You specify only the procedure header (without the equal sign and the procedure body) before the first use of the procedure, and give the full definition at a later location. This restriction and the need for forward declarations may be relaxed in a future version of Nim.
Re: Best 2D game engine for nim?
There is a fine tutorial by Dennis: [https://hookrace.net/blog/writing-a-2d-platform-game-in-nim-with-sdl2](https://hookrace.net/blog/writing-a-2d-platform-game-in-nim-with-sdl2)/
Re: Best way to convert sequence of bytes to uint32
var i: uint32 s: seq[byte] p: int s = newSeq[byte]() s.add(0) s.add(1) s.add(0) s.add(0) i = (cast[ptr uint32](addr s[p]))[] echo i output is 256, maybe not that wrong. But I am still confused, maybe Dom can add a few more pages to his book.
Re: Macro, same parameter in typed and untyped version, and other problems
Yes, I have seen that in the Nim manual. Unfortunately such a concept construction is a bit difficult because all the code is automatically generated by use of gobject-introspection. Maybe I will make one manual test case to see if it would work. For now I have broken down the procs into multiple instances in the macro: proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: CellEditable; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: SpinButton; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: ComboBox; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: SearchEntry; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: ComboBoxText; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: AppChooserButton; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) proc connect_for_signal_editing_started2(self: CellRenderer; p: proc (self: CellRenderer; editable: Entry; path: string)): culong {.discardable.} = scediting_started(self, connect_for_signal_cdecl_editing_started2, nil) connect_for_signal_editing_started2(r, handler2) Seems to work, due to overloading the compiler can select a proc definition which matches for handler2. At least the test case which a user posted compiles now -- I have to wait for user reply: [https://github.com/StefanSalewski/gintro/issues/14#issuecomment-330171244](https://github.com/StefanSalewski/gintro/issues/14#issuecomment-330171244)
Any ideas for the "Port already in Use" nimsuggest socket error?
In the last days I was going to spent some time debugging the random NEd Nim editor crashes. Unfortunately, while I got some crashes some weeks ago when working on the chess game, I was not able to generate crashes when testing. So I think I have to wait until a real crash occurs again, and then try to remember how it was generated... One problem persists. That is terminating NEd and launching it again immediately. For this case the port is still in use, and communication with nimsuggest does not work. After about two minutes port is destroyed by OS and all works again. That is a well known net communication problem of course, and not a big problem in real life. One solution is of course just waiting 2 minutes (can be up to 4 minutes from socket specs.) Another solution may be not using a fixed port number, but choosing one from a random range. But of course both is not nice. So I spent two hours for googling yesterday -- I found many questions with similar problems, but was not able to extract a solution. At least not a solution which works without modifiing nimsuggest. With modifying nimsuggest, there may be a few: Using port number 0, so that OS chooses a free port number. Or maybe ensuring that client always closes socket connection first. Or maybe setting SO_REUSEADDR flag before bind(). SO_LINGER flag with timeout 0 was also mentioned, but not recommended. https://github.com/ngtk3/NEd $ ./ned test.nim Traceback (most recent call last) ned.nim(1362)showData net.nim(1520)connect os.nim(153) raiseOSError Error: unhandled exception: Connection refused [OSError]
Re: Is nimsuggest expected to work with latest devel?
Sorry Araq, IRC just banned my IP again, so I can not answer there... No, I don't used -d:release explicitely. But nimble install should have done that I guess? Will try now with -d:release without nimble.
Re: Execution speed Nim vs. Python
> that it is really the const seq which is causing most of the slowdown That is very interesting! I strongly assume that const seg is identical to const array? Have you tested? So this may indicate that we should avoid const arrays when speed is important.
Set of enums -- some caution is needed
type E = enum a = 0 b = 1 c = 2 d = 8 EventFlag* {.size: sizeof(cint), pure.} = enum exposure = 1 pointerMotion = 2 pointerMotionHint = 3 buttonMotion = 4 button1Motion = 5 button2Motion = 6 button3Motion = 7 buttonPress = 8 buttonRelease = 9 keyPress = 10 EventMask* {.size: sizeof(cint).} = set[EventFlag] echo cast[int]({E.a}) echo cast[int]({E.b}) echo cast[int]({E.c}) echo cast[int]({E.d}) echo cast[int]({EventFlag.buttonPress}) $ nim c -r t.nim 1 2 4 256 128 Did you expect number 128 for last output line? Well I expected 256. Seems if we use sets of enums for mask in wrapper code, we have to ensure that lowest enum is zero. And insert a dummy zero if necessary. EventFlag* {.size: sizeof(cint), pure.} = enum dummy = 0 exposure = 1 pointerMotion = 2
Re: which part of std. lib can work without GC?
r3, regarding microcontrollers without operating system you may follow this thread carefully: [https://forum.nim-lang.org/t/3803](https://forum.nim-lang.org/t/3803) As you may know, when we program tiny controllers like 8 bit AVR in C or C++ we generally avoid library stuff like printf, malloc() or C++ >> << in out operations. So we would avoid that in Nim also. Current Nim stdlib uses GC, for example for strings and seq. So we may not use that, at least not when we need GC to free the objects. Note that for later Nim versions it is intended to have a stdlib which works without GC fine, so that restrictions will relax. So let us just try it, Nim should be a really nice language for embedded devices.