Re: Possible to use identifier construction to call proc by name (string)?
This is my solution to call functions by name: [https://github.com/krux02/opengl-sandbox/blob/master/examples/console.nim](https://github.com/krux02/opengl-sandbox/blob/master/examples/console.nim) This example in this project does not have any dependentcies of that project itself, it should just work stand alone.
Integrate a GLSL shader in Nim
I made a Video showing how to use an arbitrary GLSL shader and integrate it into a Nim/SDL/OpenGL application. [Here it is](https://www.youtube.com/watch?v=mcMr142BxtI)
Re: Caller line numbers in templates?
This should be an automatic solution for this problem: [https://github.com/nim-lang/Nim/pull/10569](https://github.com/nim-lang/Nim/pull/10569)
Re: How to get the address of string
I don't know how `castPointer0` is used. But my experience tells me it should never have been used in the first place. You can only take the address of the first element of a string when the string is not empty. Create an issue in the issue tracker. [https://github.com/cheatfate/asyncpg/issues](https://github.com/cheatfate/asyncpg/issues)
Re: string change from 0.18.0 on?
well you have a bug in your code, `^0` actually indexes the 0 terminator of a string, and this behavior is correct. Use `^1` instead.
Re: Problems with Bounty Source
You should put the problem you are describing in the title.
Re: Float should be 32 bit, 2x performance just by changing the defaults
This discussion is pointless and triggers too much attention. `sizeof(float)` won't change. if you want 32 bit float use float32.
Re: Perfecting Nim
I haven't been on the forum for quite a while, just the chat and I would also like to put my wishlist of things to remove here. * the range type. Well just use `type range[low,high: static[int]] = distinct int` No need for this to be a language feature * arrays with a size that is not an integer. Generics in Nim are (almost?) powerful enough to implement an array type that emulates this behavior. * int64 and int and distinct types, where float64 and float are just alias types. This is unnecessary. * concepts in their current form. I like the idea of concepts, but i don't like the current implementation/syntax. The current syntax confuses type expressions with value expressions. Changing the syntax in a non-ambiguous one will break a lot if now all code that uses concepts in the current state. It should be declared highly experimental to use concepts in the current state. * The strutils package.
Re: How to rewrite this in Nim style?
you should be able to just remove the ref in Token = ref object. That is one layer of indirection less, and therefore faster and less memory consumption. And a little comment on what you are doing. Tokens are not nested. What you are doing is already parsing. In brainfuck all tokens are characters, so tokenization is basically irrelevant. And the last part is setting current and latest. That is a very dirty way of programming. As soon as programs become more complex you will no longer know what side effects your functions have. It is better if you find a way to encode current and latest as arguments and return values. You don't need any mutable state, if you return at the top level a nested Token instead of seq. You should know that none of these recommendations are special Nim style, they are good programming style in general.
Re: How to clean up native resources properly.
There is also: > * there is also manual cleanup proc with defer > let vao = createVao() defer: vao.delete > * don't clean up at all. Resources are freed at program exit anyway. > There is no best way. There are only advantages and disadvantages. Choose wisely depending on your use case. We don't know your use case, so we don't know.
Re: How do you keep your motivation on your open-source projects
Techniques for dealing with lack of motivation, malaise, depression
Re: request for feedback - type safe OpenGL wrapper
Well, you are not the only one who wants this. I also have my opengl wrapper as part of my program here: [https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/glwrapper.nim](https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/glwrapper.nim)
Re: Pragma for temporarily making strict identifier names?
Nope, what you are looking for does not exist. All you can do is rename the Nim version of that Identifier. Be aware there are already two sdl2 wrappers around. I don't think that yet another will help anybody except yourself in learning how to write wrappers. [https://github.com/Vladar4/sdl2_nim](https://github.com/Vladar4/sdl2_nim) [https://github.com/nim-lang/sdl2](https://github.com/nim-lang/sdl2)
Re:
Vulkan introduced the _Standard Portable Immediate Representation_ (SPIR-V). You can imagine this as some sort of assembler instructions that will be compiled and optimized to the final GPU instructions from the GPU vendor driver. SPIR-V is through extensions and the latest core version also available in OpenGL and OpenCL. So I think it is a good idea to target SPIR-V.
Re: TIL more about imports
I am interested in what conflicts you have, so that you really want to use the `from foo import nil` pattern. I had conflicts, too. But I never thought about using that pattern. Because even if there is a name conflict, it does not break the import I just have to be more specific for that name conflict.
Re: Convert tuple into a Object
@jacmoe, no it's not. It is [code smell](https://en.wikipedia.org/wiki/Code_smell)
Re: Convert tuple into a Object
My intuition tells me that you did something wrong in your types, if you want to convert an object to a tuple or vice versa. Try to redesign your code so that you either only use tuples or only use objects, but don't try to make mixing them up easy. If you still want to make it easy to mix up tuple/objects yea macros will help you implement this.
Re: Defining an array inside a tuple
@rayman22201 I did the mistake you did, too in the beginning. tuple and object are both value types like a C struct, and there is no hidden vtable in an `object` unless you inherit from `RootObj`. I think the documentation is misleading here.
Re: GetType() for object type macro parameter
Pull requests that include an example in the doc comment are generally welcome.
Re: Defining an array inside a tuple
I think you should use `object`, it is the equivalent of `struct` from C. type Vec2i = object x,y: int Vec2f = object x,y: float NVGglyphPosition = int32 GlyphArray* = array[100, NVGglyphPosition] TextBuffer* = object position: Vec2f cursor : Vec2i glyphPositions : GlyphArray linePositions : seq[Vec2i] text: string
Re: Simple Python-like class macro and some python-like procedures (print, input, range, others)
@dom96 I am fairly sure that I submitted a pull request (that got accepted) not that long age that fixed the doc comments.
Re: Newbie question on generic instantiation
ther is a languare that supports what Ikalman does, it is scala. Here an excerpt from the repl. scala> val a = Left(123) a: scala.util.Left[Int,Nothing] = Left(123) scala> val b = Right("hallo") b: scala.util.Right[Nothing,String] = Right(hallo) scala> var c : Either[Int,String] = null c: Either[Int,String] = null scala> c = b c: Either[Int,String] = Right(hallo) scala> c = a c: Either[Int,String] = Left(123) scala> Scala has the `Nothing` type and type covariance. Type covariance can only work on reference types, and nim simply does not work that way.
Re: Newbie question on generic instantiation
blah blah blah: type EitherSide = enum ok, err type Either[L, R] = object case kind: EitherSide of ok: mleft: L else: mright: R proc `right=`*[L,R](this: var Either[L, R]; value: R): void = this.kind = err this.mright = value proc `left=`*[L,R](this: var Either[L, R]; value: L): void = this.kind = ok this.mleft = value proc right*[L,R](this: Either[L, R]): R = this.mright proc left*[L,R](this: Either[L, R]): L = this.mleft proc myfunc() : Either[int, string] = result.right = "Not implemented yet!" let x = myfunc() echo x.right
Re: Nim in Action is now officially in print!
I got my book today. Yay
Re: SIMD question
well, I would create simd aware types that have operators overloaded. And then I would cast to these type to use simd. # let's assume `vec' is the type with simd enabled var myArray1 = [1,2,3,4,5,6,7,8] var myArray2 = [1,1,1,1,1,1,1,1] let view1 = cast[ptr array[2, vec[int, 4]]](myArray1.addr) let view2 = cast[ptr array[2, vec[int, 4]]](myArray2.addr) view1[0] += view2[1] view1[1] += view2[0] But then you would still need to create the simd types. No idea there.
Re: Nim in Action is now officially in print!
Well as I found out, my Book is on the way, too. Yay. Well you did not get my feedback during the development of the Book, but I think you will get my feedback when I read it. Then you can use it for revision 1
Re: Practice code.
Write a game
Re: Nim newbie request/challenge
Can you put the paper on a link that is not behind a paywall? I am normally pretty trained to port from different languages to different languages, but from the paper I can't do copy paste at all.
Re: UDP socket closing after send
About the `#? braces` feature. I didn't know about it, but I actually do like it. I just prefer `{}` over indentation based blocks. But yea I think I can live with them going away. It's not essential.
Re: Gdb pretty printers for nim
I totally agree with you, debugging is really a weak spot in Nim. Things I just don't understand: By default Nim does build in debug mode, but it does not provide debugging symbols (`-g` flag for the C compiler), so that you can't actually debug with gdb your debug build. When I complain that this is an issue, I get told, that it is in fact not an issue and I should just change my `nim.cfg`. Alternatively I can simply add the `--debugger:native` flag to the compiler. The gdb integration I just showed, is something that could be done from the Nim compiler, so that all Nim applications, that are build in debug mode have already the gdb scripts self contained in the binary, so that they can be loaded from gdb automatically and work magically in any frontend for gdb. Meaning there would be nothing in the way for debug builds to work with zero configuration in every editor. But yea, it's just me who thinks this way, and passing `--debugger:native` as an additional flag to a debug build in case someone wants to actually debug the debug build is a good default.
Option type optimizations
I implemented two optimizations for the `Option` type. The idea was to do the same as the Rust compiler, use the nil/nullptr for the none option without occupying extra memory. Then I had a similar idea for `Option[Natural]`, where I could use `-1` internally to store none. That type could be used for the `find` procedure so that it does not return `int` anymore, but `Option[Natural]` without overhead. Here is the code, maybe if there is interest this might become a pull request. The think I don't like about this implementation is, `Option[Natural]` initializes to Some(0), and not None. Here is the code: import typetraits, macros type PointerType = ptr|ref|string|seq Option*[T] = object ## An optional type that stores its value and state separately in a boolean. when T is Natural: val: int # use -1 for none elif T is PointerType: val: T # use nil for none else: val: T has: bool # fallback to use an extra field UnpackError* = ref object of ValueError proc some*[T](val: T): Option[T] = ## Returns a ``Option`` that has this value. when T is Natural: result.val = int(val) elif T is seq or T is string or T is ptr or T is ref: assert val != nil result.val = val else: #assert(false == T is seq or T is string or T is ptr or T is ref) result.has = true result.val = val proc none*(T: typedesc): Option[T] {.inline.} = ## Returns a ``Option`` for this type that has no value. when T is Natural: result.val = -1 elif T is seq or T is string or T is ptr or T is ref: result.val = nil # does nothing just for clarity else: result.has = false proc option*[T,U](t: typedesc[T], val: U): Option[T] {.inline.} = when T is Natural: result.val = max(-1, val) elif T is seq or T is string or T is ptr or T is ref: result.val = val # does nothing just for clarity else: result.val = T(val) result.has = true proc isSome*[T](self: Option[T]): bool {.inline.} = when T is Natural: self.val >= 0 elif T is seq or T is string or T is ptr or T is ref: not self.val.isNil else: self.has proc isNone*[T](self: Option[T]): bool {.inline.} = when T is Natural: self.val < 0 elif T is seq or T is string or T is ptr or T is ref: self.val.isNil else: not self.has proc unsafeGet*[T](self: Option[T]): T = ## Returns the value of a ``some``. Behavior is undefined for ``none``. assert self.isSome self.val proc get*[T](self: Option[T]): T = ## Returns contents of the Option. If it is none, then an exception is ## thrown. if self.isNone: raise UnpackError(msg : "Can't obtain a value from a `none`") self.val proc get*[T](self: Option[T], otherwise: T): T = ## Returns the contents of this option or `otherwise` if the option is none. if self.isSome: self.val else: otherwise proc map*[T](self: Option[T], callback: proc (input: T)) = ## Applies a callback to the value in this Option if self.isSome: callback(self.val) proc map*[T, R](self: Option[T], callback: proc (input: T): R): Option[R] = ## Applies a callback to the value in this Option and returns an option ## containing the new value. If this option is None, None will be returned if self.isSome: some[R]( callback(self.val) ) else: none(R) proc filter*[T](self: Option[T], callback: proc (input: T): bool): Option[T] = ## Applies a callback to the value in this Option. If the callback returns ## `true`, the option is returned as a Some. If it returns false, it is ## returned as a None. if self.isSome and not callback(self.val): none(T) else: self proc `==`*(a, b: Option): bool {.inline.} = ## Returns ``true`` if both ``Option``s are ``none``, ## or if they have equal values (a.isSome and b.isSome and a.val == b.val) or (a.isNone and b.isNone) proc `$`*[T]( self: Option[T] ): string = ## Returns the contents of this option or `otherwise` if the option is none. if self.isSome: "Some(" & $self.val & ")" else: "None[" & T.name & "]" when isMainModule: import unittest, sequtils, macros suite "options": # work around a bug in unittest let intNone = none(Natural) let stringNone = none(string) test "has has": var a: Option[int] b: Option[Natural] c: Option[string] d: Option[ptr int] e: Option[ref int] f: Option[seq[int]]
Re: Gdb pretty printers for nim
well, I once did an approach to this, feel free to use it. This macro embeds the gdb python script into the executable, when it is build on Linux. Alternatively you can also load the script from gdb, but once this works there is no hassle involved anymore. [https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/debug.nim](https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/debug.nim) Here is the gdb script, but I haven't used it for a time. [https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/nim-gdb.py](https://github.com/krux02/opengl-sandbox/blob/master/fancyglpkg/nim-gdb.py)
Re: What is missing for the seq/string types to be not nil by default?
Thank you, and yes it is related. When I touch code of strings, everything becomes important.
Re: What is missing for the seq/string types to be not nil by default?
Ok the problem is somewhere in the garbage collecter. It tries to create an object and fails. My motivation to fix issues with the GC is pretty low. I would spend my time rather on removing the dependency on the GC than to fix the problem with it.
Re: What is missing for the seq/string types to be not nil by default?
well I did something in that direction on a branch. I have a problem with the nim compiler to crash here and there. How do I enable debug information again in the compiler? And why is is such a hassle in nim to get debug information? Debug builds should have them.
Re: What is missing for the seq/string types to be not nil by default?
well are you open for a pull request for that. I think that's easy to implement.
What is missing for the seq/string types to be not nil by default?
The title is the question. I would like to contribute, if I can (maybe).
Re: KDevelop nim/nimble project
Have you thought about creating an issue on the github page? I doubt that the developer still checks these forums.
Re: Nanovg and GLFW updates and Mac support
Contribution is always welcome. You are welcome, too. Thanks.
Re: Nim to C transpiler
Well nim is based on being able to compile to C. But the C code is not for readability. Even though it is quite readable.
Re: OOP Macro section of Nim by Example doesn't seem to work
Truth to be told, Nim is not yet Nim 1.0 and there is no 100% guarantee that code that you write will always work in the future. But I use a lot of metaprogramming and breaking changes are very rare. But normally when things change, the language wants you to improve your code and changes are very little and easy to fix. Don't worry too much. You can safely generate your database backing. If you will actually have the honour to see a breaking change, it will a a compilation error that can be fixed within a few minutes, nothing that will prevent you from making progress. Maybe you won't even need macros, because you can get done a lot already with generics and iterators on object members.
Re: Having a hard time getting raylib bindings to work
you can also add all c files of raylib manually with the compile pragma, like I did it in AntTweakBar [https://github.com/krux02/nimAntTweakBar/blob/master/AntTweakBar.nim#L43](https://github.com/krux02/nimAntTweakBar/blob/master/AntTweakBar.nim#L43)
Re: String slice performance!
well you can create your own StringSlice type that does not copy and override the slicing: type StringSlice src: ptr string a,b: int proc `$`(arg: StringSlice): string = (arg.src[])[arg.a .. arg.b]
Re: Thoughts on imports
well importing in a local block/function has nothing to do with runtime importing. Just see scala import. [https://en.wikibooks.org/wiki/Scala/Import](https://en.wikibooks.org/wiki/Scala/Import) and yes for your case use a when clause. The content of a when brach is at top level it does not create a new scope.
Re: How to debug nim code?
well I always put my breakpoints on functions. So like this (gdb) b foobar (gdb) b foobar_123456789987654321 it is a bit more robust on the terminal than lines. And don't underestimate `(gdb) tui enable`. I wasted a lot of time with GDB. I think it's a horrible interface, but technically it works.
Re: How to enforce usage from module scope / top level only?
Well, I would document it properly. Nim is so flexible I would not know about anything you can emit that works only top level. Maybe you can emit a function declaration that is C calling convention. Not sure if it works though.
Re: nim-random not that random at all?
The random module is not very good at all, sorry for that. But there is a mersenne twister in the standard library. This is what I use. Upper bound is exclusive. proc rand*(maxval: uint32): uint32 = let limit = uint32(high(uint32)) - uint32(high(uint32)) mod maxval var bits = rand_u32() while bits > limit: bits = rand_u32() result = bits mod maxval
Re: In-Memory Database
Well there are [tables](https://nim-lang.org/docs/tables.html#initTable,int) all in memory, just not very persistent
Re: How do fellow new comers deal with optional parenthesis dropping?
hmm, I am a bit surprised, I would have guessed the following parsing rule: echo b, c d, e f g, h echo(b, c(d, e(f(g, h # <--- I expected this echo(b, c(d), e(f(g)), h) # but hey it's this
Re: [noob] enums and index
I did not know this is possible. Seems very interesting.
Re: Nim vs D
I think the difference is in the details, but the details matter. I would really be interested to get some experience from people who actually had projects in both languages. Because then you get to know about differences that actually matter. A tiny feature of the Nim language, the dot call syntax for simple procedures in combination with the generics really changed a lot of how I structure my code. My mind is now free of class hierarchies mixins traits and all that other crap I simply don't need anymore. Maybe here and there, but I don't want it anymore, and I don't try to use it anymore to solve my problems. I did not expect this to be so nice to work with. D is more with the old fashioned class systems, at least that is what I expect it to be. I did not actually use D, I just read the documentation and presentations about it.
Re: Normalized AST presentation of the proc body
well, not that I know of. You should know that a dot expression can be a function call, but it can also be an access to an object member. I think you have to write your own normalization function.
video about my opengl sandbox project
[https://www.youtube.com/watch?v=JO0iqGDgFqA](https://www.youtube.com/watch?v=JO0iqGDgFqA) Keep in mind this is my first video that I made to demonstrate something. For me it felt totally weird to talk to a computer without response. So the slow speaking is nothing I need feedback about, I think it will improve over time when I feel more comfortable doing Videos like this. But feedback about things you understand or questions are very welcome.
Re: package like python's pandas?
Well to write wrappers, the most useful tool you have around is c2nim. That helps you with initial translations. Of course you need to also undersdand how C works or writting correct wrippers might become a bit tricky. But definitively check out other wrapper code that was already been written in Nim, so that you get an idea of how to do it. It's not necessarily a hard job to do, it is just tedious, and writing a lazy wrapper (only the parts you acutally need) might be the faster road to success.
Re: echo proper string in different consoles?
Don't use Windows. Seems to be bad software No seriously. I have no idea. I can only guess what to look for. Does msys2 try to make `getCurrentEncoding` behave correctly? Does msys2 try to make everything more unix like and make the shell utf8? Does msys2 have any information about encoding?
Re: Progress Bar using stdout.write and eraseLine()
Instead of `eraseLine` you can also always print `"\r"`. That character does not erase the line, but puts the write cursor back at the beginning of the line. output after that overrides what is already there. So in this case, where you always print the full length of the progress bar, the effect is the same as `eraseLine`.
Re: Linear algebra library
Value types have a good advantage, but the problem is, that when you make them too big, they could overflow the stack (iirc 2MB on Windows). But you should use value type arguments, because a ref type can always be converted to a value type with the `[]` operator. proc foo1(arg: Matrix): Matrix var matref1, matref2: ref Matrix matref2[] = foo1(matref1[]) The other direction is not as easy. The only problem is that the result will be a new allocation, no matter if you use ref types or not. So I suggest to also provide an api that has result arguments proc foo1(dst: var Matrix, arg: Matrix): void proc foo1(arg: Matrix): Matrix = result.foo1(arg) This allows to reuse temporary matrices more efficiently. proc foo2(arg: ref Matrix):
Re: package like python's pandas?
Well if you need docx, then find some tools that do your needs in docx. Maybe you find the right command line tools that will convert the important parts of your docx files into something that you can process. Then you can continue in Nim. Maybe you can find a C library that supports extracting the contents of a docx file nicely that you can write a wrapper for. Or you need to dygest the file on your own. Here regular expressions might be helpful.
Re: Do notation without parentheses
There was a breaking change in the do notation that I don't approve personally at all. But I thought it was parsing rules only.
Re: Binary unicode operators
Well I would like to have `¬∨∧` as aliases for `not`, `or`, `and`. But it doesn't seem that I well get it `¯\_(ツ)_/¯`
string result from macro
Normally I would think that when I return a value from a macro or set the result to that value. There would be no difference. But aparently there is: import macros macro testA: string = result = newLit("testA") macro testB: untyped = newLit("testB") macro testC: untyped = return newLit("testC") macro testD: string = newLit("testD") macro testE: string = return newLit("testE") I get the following error message: scratch.nim(14, 3) Error: type mismatch: got (NimNode) but expected 'string' Compilation exited abnormally with code 1 at Fri May 19 14:16:02 I think this is weird, because when I just set result, everything works.
Re: Surprising floating point equality
This is just a bug and should be reported let y: float32 = 47.11'f32 assert y == 47.11'f32 # < this really should be true.
Re: pointer to array?
@jxy yes there is a difference betwen `ref A` and `ptr A`. When the ref is implemented as an `std::shared_ptr` (I think Araq mentioned an option once to do that), then `ref A` takes over the ownership and as soon as the reference is deleted, also the memory will be deleted. You don't want that, therefore don't use a ref.
Re: when will [] ambiguous be solved?
Wait a moment, are you shure this D code is equivalent to the Nim code you just posted? struct Bar { void bar() { "bar".writeln; } } To me this looks like just a _method_ (in c++ terms). And a _method_ is not a value member of a struct. In other words it does not increase the size, it is just the object-oriented way to say this function takes Bar as first argument, and the syntax to call it is a bit different. But it is not stored at all in the struct. type Bar = object proc bar(arg: Bar): void = echo "bar"
Re: float64 hash
If I remember correctly, the hash function for doubles in Nim is converted over from LUA. In lua double are often used as integers because for the most part lua did not have integers like javascript. Therefore the hash function was chosen to optimize this use case.
Re: Nim Chess 2 with transposition table support is available
I did not try Vulkan yet, but I read a lot about it. More control and so on. And a unified API for both mobile and desktop. Even more things that you can do wrong and get a black screen without feedback is not really somethign I am looking forward to. My library is trying to get exactly this part away from OpenGL. Maybe because of this, my approach would be especially helpful for Vulkan developers, but I cannot tell without actually trying it out. Also I read articles on how to get Vulkan like performance with modern OpenGL techniques. Eventually I think Vulkan is very important for GPU developers, because implementing Vulkan might be much easier than implementing OpenGL (but they already did implement OpenGL so that factor doesn't not really count at this moment). And Vulkan might be very important for the big engiens like Unreal Unity and Source. Simply an environment where money and time to develop does not matter that much if it provides more performance. So my answer to that is, let the dust settle. Don't be the first one who jumps on Vulkan and regret it later.
Re: Fastest way to pack CSV file
> No, the original problem was about removing entries from a CSV file, > something which grep cannot do particularly well...  challenge accepted: grep -f delete -v data.csv > filtered.csv rm data.csv mv filtered.csv data.csv `delete` is the file with the names to delete from the data, and `data.csv` is just your data to operate on. `filtered.csv` is a temporary file. It can also be done without a temporary file by using sed instead of grep, but then it would not be grep anymore. I don't want to criticise the SQL solution, though.
Re: Nim Chess 2 with transposition table support is available
You could write a nice 3D renderer for the game state, with this library: [https://github.com/krux02/opengl-sandbox](https://github.com/krux02/opengl-sandbox) But be aware I did not define a fixed mesh format nor an _.obj_ loader because of it. So the initial renderer would use cones and spheres etc. But it would definitively a useful project for my library that would not be too much effort to implement.
Re: Blog post about Nim performance tuning
since it is basically me who took over the nim_glm maintenance. The version you fixed is very old and not the version anymore that I maintain currently anymore. I should mention that I never did performance benchmarks on that library, only correctness tests. I only applied my knowledge of what is necessary to potentionally get good performance I never actually enshured the performance was optimal. But it's good to see, that it is not horrible. One thing that I haven't seen you talk about is alignment. Have you tried to use the Vec4 type in c++ glm instead of the Vec3 type? To my knowledge only a self aligned vec4 or vec2 type can be fully optimized to use SIMD instructions. That could give c++ quite some performance that the Nim version doesn't have.
Re: Blog post about Nim performance tuning
since it is basically me who took over the nim_glm maintenance. The version you fixed is very old and not the version anymore that I maintain currently anymore. I should mention that I never did performance benchmarks on that library, only correctness tests. I only applied my knowledge of what is necessary to potentionally get good performance I never actually enshured the performance was optimal. But it's good to see, that it is not horrible. One thing that I haven't seen you talk about is alignment. Have you tried to use the Vec4 type in c++ glm instead of the Vec3 type? To my knowledge only a self aligned vec4 or vec2 type can be fully optimized to use SIMD instructions. That could give c++ quite some performance that the Nim version doesn't have.
Re: Tetris in Nim in 3D
well I know blockout, and I do like it. I actually thought to add a game mode for blockout, too. But before that, this game needs to become a but fancier.
Re: Checking in macro if proc has side effects or not
i can also imagine that the cause of compiles to fail is, that you have a double definition of the same function when you try to compile the exact same function again. So I think it would be sufficient to replace the symbolf the function with a new identifier.
Re: Checking in macro if proc has side effects or not
well, when it doesn't work it is probably a Nim bug. Create an issue.
Tetris in Nim in 3D
yay tetris > here is the sourcecode: [https://github.com/krux02/opengl-sandbox/blob/master/examples/tetris.nim](https://github.com/krux02/opengl-sandbox/blob/master/examples/tetris.nim)
Re: Checking in macro if proc has side effects or not
Well I don't know if there is something built into the language to do that simply. But you can jump to the definition of the proc symbol and get the implementation. You could add the noSideffects pragma to the function and then test if that ast still compiles with `system.compiles`.
Re: New website released!
Well I realized the single most important information (at least for me when I came to Nim) is missing on the front page of the new website: metaprogramming.
Re: New website released!
@Araq Well I did in fact know very little about the possibilities to use Nim without garbage collection. All I heared about was the `string` and `seq` are implemeneted in a way that they need the gc to run. Because I did not find any other documantation I came to the conclusion that disabling the gc is pretty much useless, because it creates leaks for nim's fundamental types. I am sorry though for the original words I had chosen. I wrote that comment when I had some frustration when writing the sizeof alignof implementation. It would be nice if there would be a little bit more documantation oft the garbage collection in Nim. Especially on how to use Nim, when there is no GC.
Re: How do I debug the Nim compiler?
I found out how to do it: nim c --lineDir:off --debuginfo compiler/nim
Re: New website released!
Well, when you say that GC is optional, you should say that disabling it pretty much makes the types seq and string unusable, and therefore the GC is not really optional.
How do I debug the Nim compiler?
I have a problem I have absolutely no clue why this happens: [https://github.com/nim-lang/Nim/pull/5664](https://github.com/nim-lang/Nim/pull/5664) In order to find out why this happens I would like to debug the compiler. Since I think that the problem is somewhere in the generated C code I would like to debug the generated C code. This means I would like to compile the nim files in release mode (no source map), but then when I compile the c files, I would like to compile them with debug information, so that I can see where in the C code I am. So how can I do this?
Re: book delayed again
@Fungi well you do not have the best diplomatic strength. When you write in a Forum for Nim developers that what they are doing is entirely wrong and sucks a lot, then you will earn a lot of hate. You are right, performance is not everything. But Nim is not entirely about performance, it is about control in compiled environments. For me it is the only language that gives me the amount of freedom in terms of metaprogramming combined with the control over memory layouts that I need to control the rendering pipeline. If you don't do GPU rendering or some other high performance computing stuff. That is fine, but just because you don't need it, don't assume nobody will ever need it. Accept that you only know a tiny part of programming.
Re: book delayed again
@Fungi, it's nice that you found out that Nim is not the language for you, but you should understand that everybody's point of view is always a very limited view on the world. Nobody knows everything. What I want to say is, just because you don't see the advantages of compiled programming languages in your domain of expertise, it doesn't mean that this will apply to other people as well. But you are right that the debugging experience in Nim is Bad.
Re: Can var proc parameters be faster than function results?
I think for a fair comparison, you should zero out the memory in the `var`-parameter case, because that is done for the result variable and therefore would be the only fair comparison. But I think even then it would not explain the big difference.
Re: ref object or object with ref field
@LeuGim well when you have an array of RootObj, not a ref/ptr to RootObj in the array, the array actually doesn't contain the subtype anymore. So sure when you iterate and call foo on each object. It does call the method from RootObj, but only because you actually have a true RootObj value there. @Lando That is correct when you mean by reference type all variants of reference types, including the hidden pointer that is used on function arguments. What I want to say is that the restriction on reference types is almost irrelevant.
Re: ref object or object with ref field
@dom96 I am well aware that seq is implemented as a pointer, but it has value semantics. That is the reason I did not mention it. var a = @[1,2,3] var b = a # b is now a new copy of a
Re: Cello: a library of string algoritms using succinct data structures
@andrea About the issue. You are right I should explain a bit more. I try to get something as [std::span](https://forum.nim-lang.org/open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0122r1.pdf) from c++ into the standard library of Nim. That document explains it much better that I could do it in this post. The idea is that you could easily transform a memory mapped files, strings and seq types into a span, and then use this as an interface for your API. There is no need to know that the data is actually from a memory mapped file in your library. I should actually put that link to the pdf to the original issue, too. I was not able to find this originally when I wrote the issue.
Re: ref object or object with ref field
@Lando here an example for dynamic dispatch on value types. type A = object of RootObj a: string B = object of RootObj a:int method foo(arg: RootObj): void = discard method foo(arg: A): void = echo "A ", arg.a method foo(arg: B): void = echo "B ", arg.a var a = A(a: "abc") var b = B(a: 12345) var pointers : array[2, ptr RootObj] = [a.addr, b.addr] for p in pointers: p[].foo var references : array[2, ref RootObj]= [new(A), new(B)] for p in references: p[].foo
Re: ref object or object with ref field
@Varriount: What I originally meant was a pointer to the Context struct itself. But you are right I was not clear on that. For elements in a seq an index works pretty well. But to your comment on ret types I like to disagree. I don't like to say out in the blue that reference types are like C pointers but safer. If that would be the full truth, then `ref` would be generally better than `ptr` types, and that is not true. My take on explaining ref types is, a `ref` is like a `ptr` but with lifetime management. A `ref` keeps it's target object alive, as long as there is still a ref to it, and ensures it's destruction when it is not referenced anymore. Objects on the stack already have a defined lifetime, therefore you should reference them with pointers. Function parameters are when it makes sense passed as hidden pointers, therefore it is neven an optimization to pass a `ptr` to a function instead of a value type. This basically removes 90% of all cases where you would use a pointer in the C context, and therefore you only need `ptr` here and there. And ref types, well I didn't need it for anything yet, but they are probably very useful for arbitrarily shaped graphs.
Re: ref object or object with ref field
Yes, when you use it. The following example has quite some performance difference depending on the type chosen: var context: Context = ... [...] let nodes = context.nodes But without context it's hard to give advice. My guess is that the performance difference doesn't matter, and when it does, you should do performance test. The best performance is by the way the type that has the fewest indirections: type Context*[T] = object nodes: seq[Node[T]] but be aware that if you assign Context to another variable, you will create a deep copy. So when you want to have a reference stored in another variable, you should use the `addr` operator.
Re: Cello: a library of string algoritms using succinct data structures
@bpr sorry, bioinformatics then. What I originally mean is 'people who write programs that handle genes' and I naïvely used the term "genetic engineer" which is of course wrong. I am just an application developer. All strings I handle are the strings I have written manually that are necessary for the program to some text, and maybe some grep and sed on the command line. So no need for any external library.
Re: Cello: a library of string algoritms using succinct data structures
Well it is for genetics. No wonder that I initially didn't get what it was about. I am not a genetic engineer. I saw that you had a spill datatype. I think it is related to this issue, it would be nice, if you could also give a comment on it, because I think not all libraries should define this with their own name for it. [https://github.com/nim-lang/Nim/issues/5437](https://github.com/nim-lang/Nim/issues/5437)
Re: Closure iterators seems to be broken or I am missing something?
Yes I think you should file a bug. If you do it, I suggest to put both versions in (working/non-working). Maybe if you can you could try to look at the generated C code, and if you understand it, point out the significant difference. Btw the generated C code looks much nicer, when you compile with `-d:release` (much more compact).
Re: Closure iterators seems to be broken or I am missing something?
Ok, I got it working with low level iterator code: proc len[T](it : (iterator : T)) : Natural = for i in it(): result += 1 proc filter[T](it: (iterator : T), f: proc(x: T): bool): (iterator: T) = return iterator(): T = while true: let x = it() if finished(it): break else: if f(x): yield x proc simpleSeqIterator[T](s :seq[T]) : (iterator : T) = iterator it: T {.closure.} = for x in s: yield x return it let a = toSeq(1 .. 99) echo len(a) echo len(simpleSeqIterator(a)) echo len(filter(simpleSeqIterator(a), proc(x : int) : bool = true)) I also once tried to do functional programming in Nim, but there is a lot of friction to do so at the moment. One thing I did that could also be useful for you was a lifting template that allowed me to transform an inline iterator into a closure iterator, so that I could use all those iterators that were only defined as inline iterators in the standard library more useful.
Re: Closure iterators seems to be broken or I am missing something?
I currently try to get this working. As it seems there is definitively a bug in Nim. But you also have a bug. You reuse `iter`. After you first calculated `len(iter)` iter is at it's end, and therefore consumed. But even fixing that doesn't bring you the result you hoped to get.
Re: How to properly bind a function to a compiler buildin?
@cblake I think it should be handled at nim level, because it can be hadled at Nim level. The more things can be resolved at the Nim side, the more powerful the language is. On the other side, Nim does not only have a C backend, it also has an LLVM backend. I do not know the state of this backend or how LLVM actually works, but I could imagine that here it is part of the nim compiler to define the alignment. And it is also not too complicated to implement this behaviour backend dependent. The algorithm that runs on each backend is exactly the same, it is only the alignment value of different types that might change between backends. So it boils down to a simple mapping from a type bachend pairr to an alignment value. This map needs to be complete though.
Re: How to properly bind a function to a compiler buildin?
@Araq I just looked at `magicsAfterOverloadResolution`, since you said it is the preferred way. I tried to find the `mSizeOf` handling in there for an example, but it is not handled there. I would like to know what I am actually supposed to do in this procedure. What information do the parameters provide to me? And what am I supposed to return? Currently the procedure itself does not have any documentation string, nor does any of the procedure argument types have any documentation. So my question here is, what are the parameters, and what should it return? Especially the parameter `c: PContext` is a bit confusing to me. Since I already used `PNode` a bit, I guess it should eventually return an integer literal in form of a PNode with the value of the offset/alignment/size.
Re: How to properly bind a function to a compiler buildin?
@cblake To my research Each platform (x86 arm powerpc) may have different alignment rules. But there is definitively no alignment rule distinction between compilers, otherwise it would be impossible to use structs as interfaces in C. This makes header files in C compatible between different compilers. This compatibility was never enforced or was defined, the C standard actually would allow different behaviours, but compiler manufacturers wanted compatibility and that is what we can rely on today. I am aware of the `packed` attribute, I think nim should have the same. To your last question. I think I can move the resolution of the alignment parameter to the runtime, but that would not only increase the complexity of the code a lot, but also remove the ability for compile time error checking. As far as I know the target platform is already known at compile time, and therefore the generated C code is already platform dependent. This means it would not be wrong at all to generate platform dependent constants in the C code, because other platforms would have different C code anyway.
How to properly bind a function to a compiler buildin?
Currently I improve the proceduer `computeSize` in `types.nim`. I worked now quite a bit on the procedure, but I don't understand, how `system.sizeof` eventually calls `types.computeSize`. I know that in some cases the call system.sizeof was not able to be evaluated at compile time. I would like to know how this decision is made. Eventually I would like to add `system.alignof` analogue to `system.sizeof`. Then I would like to add offsetof, but here I do not know how the interface should look like. This is an idea: proc offsetof[T](typ: typedesc[T]; member: untyped): int For my use case it is very important, that I can get all the sizes at compile time, therefore I would like to make all this also available with NimNode arguments: # macros.nim proc sizeof(typ: NimNode) proc alignof(typ: NimNode) proc offsetof(member: NimNode) But here again, I don't understand how I can bind these procedures to the functions I defined in `types.nim`.
Re: why is nim install weird?
I can only support the workflow Araq suggested, I do the same. You can then add `~/projects/Nim/bin` to your path, or symlink the binaries from there to a folder that is already in your path. I have `~/bin` in my path and put the symlinks there. `make install` should not be done with any software at all. You can't get rid of it anymore.
Re: How get a type of what used to be an untyped NimNode in macro
I solved this problem with a two layer macro. The outer macro had an untyped argument and an inner macro with a typed argument. The outer macro was the macro that the user of the dsl would call and it has the nice syntax to call it. The outer macro transforms the untyped ast in an ast that then can be type checked. I did this by adding some function calls that didn't do anything, they were just there, so that the type checker could do it's job. The now typecheckable ast is then passed to the inner macro that has a typed argument. Now you can do whatever you want from here on. In your case the outer macro would generate the let expression you talked about. over simplifiled example: proc decoration[T](arg: T): int = 1 macro inner(arg: typed): untyped = [...] macro outer*(arg: untyped) = result = quote do: inner: decoration(`arg`)