Re: dynamically creating a tuples
Have you seen [this thread](https://forum.nim-lang.org/t/2482)? >From what you're writing, it is hard to understand what you want to do.
Re: Upgrading to Nim 0.17.0
Okay, that worked. Should have tried beforehand, but I though removing all `nimcache` dirs should be sufficient.
Upgrading to Nim 0.17.0
I am trying to update Nim to 0.17.0. I am on current master branch. Since rebuilding with koch failed, I updated the csources and built nim from there – no problems. Then, I try to rebuild koch with the new Nim. This generates the following error output: Hint: used config file '/Users/flyx/Projects/3rdParty/Nim/config/nim.cfg' [Conf] Hint: used config file '/Users/flyx/Projects/3rdParty/Nim/koch.nim.cfg' [Conf] Hint: system [Processing] Hint: koch [Processing] Hint: os [Processing] Hint: strutils [Processing] Hint: parseutils [Processing] Hint: math [Processing] Hint: algorithm [Processing] Hint: times [Processing] Hint: posix [Processing] Hint: parseopt [Processing] Hint: osproc [Processing] Hint: strtabs [Processing] Hint: hashes [Processing] Hint: etcpriv [Processing] Hint: streams [Processing] Hint: cpuinfo [Processing] Hint: kqueue [Processing] CC: compiler_koch CC: stdlib_system CC: stdlib_os CC: stdlib_strutils CC: stdlib_parseutils CC: stdlib_math CC: stdlib_algorithm CC: stdlib_times Error: execution of an external compiler program 'clang -c -w -I/Users/flyx/Projects/3rdParty/Nim/lib -o /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.o /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c' failed with exit code: 1 /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:322:30: error: expected ';' after expression nimfr_("find", "system.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:364:34: error: expected ';' after expression nimfr_("contains", "system.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:379:34: error: expected ';' after expression nimfr_("contains", "system.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:393:28: error: expected ';' after expression nimfr_("*=", "system.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:400:28: error: expected ';' after expression nimfr_("+=", "system.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:425:36: error: expected ';' after expression nimfr_("intToStr", "strutils.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:466:34: error: expected ';' after expression nimfr_("repeat", "strutils.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:492:31: error: expected ';' after expression nimfr_("usrToCell", "gc.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:501:31: error: expected ';' after expression nimfr_("rtlAddZCT", "gc.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:508:36: error: expected ';' after expression nimfr_("asgnRefNoCycle", "gc.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:547:36: error: expected ';' after expression nimfr_("parseInt", "strutils.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:621:40: error: expected ';' after expression nimfr_("toLowerAscii", "strutils.nim") ^ ; /Users/flyx/Projects/3rdParty/Nim/nimcache/stdlib_strutils.c:644:40: error: expected ';' after expression nimfr_("toLowerAscii", "strutils.nim") ^
Re: New here. can't seem to get the installer to work.
You have to give us some information to work with. For example, what C compiler are you using? And what's the output of the `sh build.sh` command when building from source? Since `bin/nim` doesn't exist afterwards, this is probably the problem, and the output most probably gives you the reason why it fails.
Re: Alternative for {.immediate.}
Shouldn't it suffice to make `e` `untyped`?
Re: How check if expression has a type without triggering compilation failure
… because it is mentioned in the [system module's documentation](https://nim-lang.org/docs/system.html#compiles,expr).
Re: Procedure which returns procedure
Your code does not work because you are using `func` as identifier, which is a reserved keyword. I demangled it a bit and renamed `func` to `fun`: type MyProc1 = proc() MyProc2 = proc(p: MyProc1) MyProc3 = proc(p: MyProc1): MyProc1 proc applyAllSync(funcs: seq[MyProc2], onAllDone: MyProc1) = fold(funcs, proc(onDoneNothing: MyProc1) = onDoneNothing, proc(doBefore: MyProc3, fun: MyProc2) = return (proc(onDone: MyProc1): MyProc1 = return doBefore(proc() = fun(onDone) ) )(onAllDone)() )
Re: Procedure which returns procedure
Your JS is horrible to read as it lacks type information (what is funcs, what is onAllDone, what is doBefore etc). I tried to interpret it but gave up. You should rather explain what you want to do than giving us this piece of code.
Re: Procedure which returns procedure
Try: proc pprint[T1](ann: string): (proc(t0: T1): T1) = return proc(val: T1): T1 = return val echo pprint[int]("test")(42)
Re: Alternative comment syntax
@hcorion This is Neo2 (it states that itself) and it is an image for printing and gluing on the keys. Therefore, there are multiple meta-key images to choose from.
Re: Alternative comment syntax
> One key # is found only in UK and Ireland a far as I know. Germany… > Any keyboard, any standard, with numeric keypad, has + - * and /. So moving your hand over to the numpad and back is faster than pressing two keys? > Just need people to think more open minded and understand that "this feature" > adds much more than takes. Ad hominem again. You assume that people who oppose your proposition are not „open minded“ (enough). > To be true, it just adds. So far, none of your arguments convinced me even a bit that this _adds_ anything beyond complexity.
Re: Alternative comment syntax
> No attacks against anyone You called people > pythonic purists which is obviously referring to people rather than the issue itself. > I have no problems. Your previous posts sounded differently. > I want to help. Accept or deny. Lacking commitment to discuss does not make your proposal look better. > In my keyboard both '#' and '/' takes two keystrokes. For the record, my keyboard has a one-key `#`, but `/` takes two keys. However, I don't use the standard keyboard layout anyway.
Re: Alternative comment syntax
> 1\. Many keyboards does not have an one key access to "#", > as the "/" key, > mine for instance, I usually need to look at alt-3 > or shift-3 combination. Same is true for almost all other special characters which are used often in Nim, e.g.: `(`, `)`, `:`, `=`. I do not see how `#` is different from them. > 2\. Most languages adopts a C++ like approach to use the one key "/" > found > in many US based keyboards. So first you argue about _many keyboards_, but suddenly, because it fits your cause, the US layout is the important one? What about all the other layouts that don't have a `/` key (quite a lot don't)? > 3\. People from Go, C++, Delphi, Rust, Xojo, Java, Javascript, Swift... > are > used to // double slash comments People from Python, Scheme, Visual Basic, Bash, Ada, Haskell, Ruby... are not. Also, all those people are used to a different syntax than Nim has, so why, of all syntactic elements, should the comment syntax be kept? > It just attracts more users, adds more fun, beautify the language, > and > makes more people feel at home. Without presenting any evidence, this is just your personal opinion. > I like the language, but I hate the "#" so much (as others) So far, you are the only one who is complaining. > and try to convince pythonic purists This is ad hominem and therefore not a valid argument. > there is a huge team of "//" lovers out there As I said, I only see you complaining. > Well, I consider this a bad preliminary choice, it's confusing clashing > > directly with the already diffused use of // everywhere. _Everywhere_ in the sense of _every language you listed, ignoring all those that use different commenting styles_. Your arguments are all bad and show that this is mostly an issue for yourself, because, as you state yourself, you hate `#` _so much_. Your points about keyboard layouts are not valid since you can simply change the keyboard layout. But instead of using tools that are more fit for the job, you urge others to fix your problems.
Re: Macro with runtime arguments
The macro will slurp `if debug: true else: false` as expression. It will not be resolved; instead, inside the macro, you will have this whole expression in your variable `debug`. > Is there a way to 'extract' the boolean value of (the identifier) debug in > the macro It does not have a value when the macro is executed. The macro is executed at compile-time. The `debug` in `main()` is a `let` variable, i.e. is set at run-time. The macro cannot possibly know its value when it executes, because it isn't set yet. > The macro I'm messing with is the body of a loop that gets executed many > times; while I can make it a simple procedure, the performance goes down > considerably. It seems like you want to use a simple template instead: template dumbMacro(debug: bool = false): typed = if debug: stderr.writeLine "DEBUG ON" echo "Hello from dumbMacro!" proc main() = let debug = "-d" in commandLineParams() dumbMacro debug when isMainModule: main()
Re: I compiled libui.dll file is not successful
By the way, you can check dependencies of your DLL with dumpbin.exe /dependents libui.dll (given that you have Visual Studio installed; it's in the VC bin folder)
Re: I compiled libui.dll file is not successful
> You may doubt that, but when run my Windows application alongside my "old" > libui.dll, the GUI program runs fine. That may be because it requires a version of MSVCP**.dll which is available on your system. Or yes, because it has been statically linked into it. > Do you know a good source where I could download MSVCP140.dll as standalone > file? It is included in the linked installer. I would never download it anywhere else than from Microsoft itself – there are versions available on shady sites. You may succeed in opening the installer with 7zip or something on Windows. Otherwise, you need a minimal Windows VM, install it there, and then fetch the file.
Re: I compiled libui.dll file is not successful
> But I have a version of libui.dll (linked above), which does not have this > dependency and runs fine I highly doubt it. The MSVCP140.dll is the C/C++ standard library on Windows, and almost every C/C++ program depends on it. Typically, Windows has some version(s) of this dll already preinstalled, in which case you do not need to redistribute it – it just works. However, when other versions are required than those that are present, you need to either bundle them or require the user to install them.
Re: I compiled libui.dll file is not successful
Well there are a lot of programs which just bundle MSVCP140.dll with their executable, like you do with libui.dll. So why not just place MSVCP140.dll next to it? > It's also possible to directly install redistributable Visual C++ DLLs in the > application local folder, which is the folder that contains your executable > application file. (From [here](https://msdn.microsoft.com/en-us/library/ms235299.aspx))
Re: Macro with runtime arguments
`debug` is an identifier and does not have a `boolVal`. You want to have `dumbMacro true` instead of `dumbMacro debug`.
Re: I compiled libui.dll file is not successful
> complaining about a missing MSVCP140.dll So why don't you just [download](https://www.microsoft.com/en-gb/download/details.aspx?id=48145) and install it?
Re: Canonical idiom for opening files?
For ensuring file closing: var fh = open(filename) defer close(fh) # close fh at the end of current block process(fh) Encoding is not part of the file opening process in Nim. A file is just read byte for byte. If, for example, you want to open a latin-1 file and get a UTF-8 string, you could do this: import encodings var content = convert(readAll(filename), srcEncoding="ISO-8859-1") Note that I am using `readAll` which opens and closes the file automatically. You can also use the method shown above, instantiate an `EncodingConverter` and then read and convert each line / character / whatever individually.
Re: How to be more concise in code [NEWBIE]
> but did not want to use inheritance and methods because it needs heap > allocation You are using strings so your objects are doing heap allocations anyway. You should replace the strings with IDs of the target which got hit / died if you don't want any heap allocation. You can of course do something similar to dynamic dispatching without polymorphism: type MessageType = enum msgHit, msgDeath, msgDayNight type Message* = object textImpl: proc(m: Message): string case messageType*: MessageType of msgHit: target*: string hp*: int of msgDeath: died*: string of msgDayNight: isDay*: bool proc hit*(target: string, hp: int): Message = Message(messageType: msgHit, target: target, hp: hp, textImpl: proc(m: Message): string = "You hit " & m.target & " for " & $m.hp & " HP." ) proc death*(died: string): Message = Message(messageType: msgDeath, died: died, textImpl: proc(m: Message): string = m.died & " just died." ) proc dayNight*(isDay: bool): Message = Message(messageType: msgDayNight, isDay: isDay, textImpl: proc(m: Message): string = if m.isDay: result = "The day has just begun." else: result = "Beware! Night is coming." ) proc getText*(m: Message): string = m.textImpl(m)
Re: Chocolatey Package for Nim?
With the same argument, it would also be necessary for Nim to have an official package for debian, Fedora, Arch, Nix, Homebrew… I think maintaining packages is in better hands with those people who use the package managers.
Re: Forum rules
There are no official rules. There have been threads about having a CoC and the majority was against it. General opinion usually is _„instead of thinking about rules, just write some Nim code“_. There also isn't some big sign on your front door which tells you how to behave while out on the street, yet people get along with each other most of the time.
Re: Return SUM types from proc
> Regarding pointers being the only option for polymorphic returns; I guess > this depends on the object layout used? For instance, I assume object variant > does not need to be same size but still allows polymorphism in return value, > simply by reserving space for the biggest variant in the calling stackfram. Object variants are not polymorphism (at least not in the computer science semantics of the word). But you are right, it works because it reserves the size of the largest possible variant. One obvious difference to polymorphism is that whoever defines the object type has complete control over any variants. With polymorphism, a user of your type can define a new subtype. This is why using `if v of SomeType` is bad style – you cannot know all derived types, because other code using your code may define new derived types.
Re: Return SUM types from proc
Generally speaking, whenever you are using `if v of SomeType`, you are holding it wrong. Polymorphism gives you the power of defining dispatching methods for operations whose implementation differs based on which subtype your variable holds. If implementing your code with dispatching methods seems clumsy or simply does not fit your coding style, use object variants instead. The question of whether the values should reside on the stack or on the heap is a different one. For example, [JsonNode](http://nim-lang.org/docs/json.html#JsonNode) is an object with variants but also a `ref` type residing on the heap.
Re: Return SUM types from proc
References (or pointers) are a prerequisite for runtime polymorphism since they are the only way to have differently typed values fit into the same memory location, since all pointers have the same size. Might not be true for all languages.
Re: Return SUM types from proc
`A or B` needs to be collapsed to one definite type at compile time. It is typically used for parameter types where the compiler sees which type is given at the calling site. This is not applicable if you want your return values to have different types at runtime. There are multiple solutions. First solution is derived types: type Base = ref object of RootObj A = ref object of Base a_value: int B = ref object of Base b_value: int proc test(arg: int): Base = if arg < 0: return A(a_value: arg) else: return B(b_value: arg) let a = test(10) let b = test(-5) Another solution is object variants: type RetKind = enum A, B Ret = object case kind: RetKind of A: a_value: int of B: b_value: int proc test(arg: int): Ret = if arg < 0: return Ret(kind: A, a_value: arg) else: return Ret(kind: B, b_value: arg) let a = test(10) let b = test(-5)
Re: var param vs tuple as return value
Well there's a [nim](http://stackoverflow.com/questions/tagged/nim) tag on StackOverflow. It certainly wouldn't harm if Nim had more exposure there. I think this forum should be more for discussions which do not fit into SO's Q&A format.
Re: How to understand pragmas in Nim?
proc compile(code: string): {.compileTime.} NimNode = This is a syntax error because the proper syntax would be: proc compile(code: string): NimNode {.compileTime.} = Partly related: Ada is in a similar state. In the rationale of Ada 83, pragmas were described as having _no influence on the meaning of the program_. Then, Ada 95 came along and used pragmas for all sorts of things, including some which changed the meaning of the code. For Ada 2012, a solution was sought and found; it was a new part of the syntax named _aspects_. So, instead of this: procedure Flush; pragma Import (StdCall, Flush, "glFlush"); You could now write procedure Flush with Import => True, Convention => StdCall, External_Name => "glFlush"; This is pretty close to how Nim pragmas already work, as they can already be tied to some entity instead of being standalone. For me, the concept seems to be closer to aspects than to traditional pragmas. C# and Java have attributes/annotations which _have_ to be bound to some entity. They are also part of the reflection descriptors, so they are pretty different from what traditionally is called a pragma. However, some still have the concept of being a hint to the compiler (for example, @Synchronized in Java). To summarize: Pragmas in a language are semantically placed on an axis somewhere between „compiler hints“ and „part of the language semantics“. The trend seems to be towards the latter, but the word _pragma_ is usually bound to the former, so some languages call them differently. Nim calls them pragmas but also supports the annotation/aspect semantics, and enables users to define „new pragmas“ via macros. Which is conceptually not very different to what C# and Java do, it is only much more powerful because the semantics can be given in the macro implementation, while in Java, the semantics of an Annotation is defined somewhere else.
Re: No way to run my code, idk how to force a float as an Int
This happens because `/` on ints returns a float. You want to use `div` instead, which is integer division. var maxLignes = ((nombreDePyramides + 2) * (nombreDePyramides + 3)) div 2 - 4 Or, alternatively, convert it – this is clearly the inferior solution, but given here for completeness: var maxLignes = int((nombreDePyramides+2)*(nombreDePyramides+3)/2-4) In both cases, you do not need to give the type because it is derived from the expression.
Re: Nim VFS (virtual file system)
Some thoughts: The idea seems to be basically what Java does with `*.jar` files. And you say Tcl also does it. So why can they do this? They can because running both a Java application and a Tcl script requires a runtime environment (Tcl interpreter / JRE) on the target machine. So if the user must install this runtime environment anyway, it is minimal pain to add such a VFS to it. Nim, on the other hand, does not depend on a special runtime environment (no more than C applications, anyway). So providing Nim artifacts in the form of a VFS would suddenly require users of Nim applications to install an additional tool. This is clearly an inconvenience and the question is whether the benefits of this VFS amortize this inconvenience. In contrast to Java, Nim libraries are usually compiled into the application. I have never seen a Nim lib that is dynamically linked to other Nim code. So for libraries, the source code is distributed. This will, of course, not always be the case – when a Nim library requires non-code resource files on its own, it will need a way to tell an application that it needs those files. This is where a VFS approach may come in handy. Resources are usually necessary for GUI libraries, which is a special case, but also may be useful for things like i18n. So we may need a more sophisticated approach for including libraries than just `nimble install`. But this can all be done at compile time with a bundling script. I think the better thing to have would be a bundler that can build native bundles for common target platforms, like an `.app` bundle for macOS, a `.deb` / `.rpm` package for some Linux distributions and an installer for Windows. This bundler would also have a minimal API for platform-independent access to application resources (which will be put in `/usr/share` on Linux, but inside the app bundle / installation directory in macOS / Windows). So, basically, I am suggesting that an API that emulates some kind of VFS would be good but the backend should be the application resource management native to the target system instead of some zipped file.
Re: Please , can we stop spams?
Having a GitHub account should not be required to participate in the community and I think it's harmful to make people with few original Nim code second-class citizens.
Re: Return values question
Interesting. I only remember that Araq once explained that strings and seqs are heap objects managed by the garbage collector, but I may have misunderstood it. In any case, there should be some official documentation about this.
Re: Return values question
> When a shallow sequence is resized, only the variable currently being > modified has its reference updated; the other variables will still have > references to the old data. proc foo() = var a = newSeqOfCap[int](2) a.add(1) var b: seq[int] shallowCopy(b, a) a[0] = 0 # modify sequence after copying a.add(2) # further modification echo a echo b b.add(3) # resizing happening here! echo a echo b foo() This outputs: @[0, 2] @[0, 2] @[0, 2, 3] @[0, 2, 3] Modifications after shallow copying are fine because strings and seqs are garbage-collected heap-objects. As you see, both references are still fine after resizing happened.
Re: Newyear is coming , is 2017 the year for nim?
I have heard that 2017 will already be the year of Linux on the desktop, so Nim might have to wait one more year.
Re: Using Nimscript as an embedded scripting language?
> Is it possible to use Nimscript as an embedded scripting language In theory: Yes, of course. Why shouldn't it? In practice: Since the compiler and the standard library are rather modular, you can include parts of it in your project. However, there is no API dedicated to what you want to do, so you would need to extend and modify quite a bit of the current code. I believe that Lua's API for embedding the interpreter would still be superior as it was designed with embedding in mind. Not mentioning the restrictions of Nim's VM (for example, using `ref` variables is still buggy). Lua's embedding API is also designed for safety as you can tightly control which parts of the standard library will be available. It would be a lot of work to reimplement that for Nim – for example, you would need to split up the `system` module since it contains a lot of stuff you may not want to make available (like File I/O), while other things are absolutely necessary (basic types and procs, e.g. for strings, arrays and seqs).
Re: Same line versus single-line block in the AST
> And usually there are no parts in the AST that are "always" there to always > ignore Well that's good to know :). I wrongly assumed by testing that the `RecList` will always be there.
Same line versus single-line block in the AST
Consider this code: import macros dumpTree: type ObjectKind = enum oA, oB ObjectType = object case kind: ObjectKind of oA: a: string of oB: b: string ObjectType2 = object case kind: ObjectKind of oA: a: string of oB: b: string proc foo(): int = 2 proc bar(): int = 2 It outputs: StmtList TypeSection TypeDef Ident !"ObjectKind" Empty EnumTy Empty Ident !"oA" Ident !"oB" TypeDef Ident !"ObjectType" Empty ObjectTy Empty Empty RecList RecCase IdentDefs Ident !"kind" Ident !"ObjectKind" Empty OfBranch Ident !"oA" RecList IdentDefs Ident !"a" Ident !"string" Empty OfBranch Ident !"oB" RecList IdentDefs Ident !"b" Ident !"string" Empty TypeDef Ident !"ObjectType2" Empty ObjectTy Empty Empty RecList RecCase IdentDefs Ident !"kind" Ident !"ObjectKind" Empty OfBranch Ident !"oA" IdentDefs Ident !"a" Ident !"string" Empty OfBranch Ident !"oB" IdentDefs Ident !"b" Ident !"string" Empty ProcDef Ident !"foo" Empty Empty FormalParams Ident !"int" Empty Empty StmtList IntLit 2 ProcDef Ident !"bar" Empty Empty FormalParams Ident !"int" Empty Empty StmtList IntLit 2 As you can see, the declaration of `ObjectType` produces `RecList` s inside its case branches, while `ObjectType2` does not. I think it would be good for both cases to produce the same AST since they are equivalent. As comparison, I added the two proc defs at the end: Both produce a wrapping `StmtList` although one has its implementation on the same line and one in the next line. My problem is that a specification of how the AST will look like exactly is currently missing, so I usually just look at the AST that is produced. And that way, I may overlook things like „if a variable declaration is on the same line as the of branch, no wrapping `RecList` is produced“.
Re: NimYAML 0.7.0 released
`loadToJson` ignores tags because the JSON structures do not know anything about tags. You have several options: **Using the serialization API with an implicit variant object** First, you need to define the type for the tag `!remote`. You need to tell NimYAML how to load that type. Then, you define a variant object type that can hold either normal strings or `!remote` values. You then tell NimYAML to treat this variant object type implicitly for loading the chapters. Example code: import yaml.serialization, yaml.taglib type Remote = distinct string ChapterKind = enum ckLocal, ckRemote Chapter = object case kind: ChapterKind of ckLocal: lValue: string of ckRemote: rValue: Remote Root = object chapters: seq[Chapter] proc constructObject*(s: var YamlStream, c: ConstructionContext, result: var Remote) = # construct a Remote like a string constructObject(s, c, string(result)) setTagUri(Remote, "!remote") markAsImplicit(Chapter) var root: Root load(""" chapters: - foo - bar - !remote http://example.com/somefile """, root) echo "Parsed chapters:" for c in root.chapters: case c.kind of ckLocal: echo "[Local] ", c.lValue of ckRemote: echo "[Remote] ", string(c.rValue) Sadly, you cannot simply transform the chapter values into some `tuple[value: String, remote: bool]` because NimYAML's serialization API uses tags to denote types, not annotations. **Using the DOM API** Perhaps simpler for simple use cases: import yaml.dom var document = loadDOM(""" chapters: - foo - bar - !remote http://example.com/somefile """) echo "Parsed chapters:" for c in document.root.pairs[0].value.children: echo if c.tag == "!remote": "[Remote] " else: "[Local] ", c.content The DOM API needs some love; currently mappings are parsed into a `seq[tuple[key, value: YamlNode]]` which is not ideal for accessing specific subtrees. A Table would make more sense. Pull requests are welcome :). **Using the sequential API** This may be useful for use cases where you need to process the input sequentially since it doesn't load everything in an object and therefore is faster: import yaml.parser, yaml.taglib, yaml.stream var myTagLib = initCoreTagLibrary() yTagRemote = myTagLib.registerUri("!remote") p = newYamlParser(myTagLib) events = p.parse(""" chapters: - foo - bar - !remote http://example.com/somefile """) doAssert events.next().kind == yamlStartDoc doAssert events.next().kind == yamlStartMap let key = events.next() doAssert key.kind == yamlScalar doAssert key.scalarContent == "chapters" doAssert events.next().kind == yamlStartSeq var cur = events.next() echo "Parsed chapters:" while cur.kind != yamlEndSeq: doAssert cur.kind == yamlScalar echo if cur.scalarTag == yTagRemote: "[Remote] " else: "[Local] ", cur.scalarContent cur = events.next() doAssert events.next().kind == yamlEndMap doAssert events.next().kind == yamlEndDoc doAssert events.finished()
Re: noob: json to object conversion
Since YAML is a superset of JSON, you can use [NimYAML](http://forum.nim-lang.org///nimyaml.org) to deserialize the JSON file. It is able to automatically map a JSON object to a Nim object: import yaml.serialization, streams type Config = object rootDev: string grubDevLabel: string title: string updateGrubDir: string proc readConfig(): Config = var s = newStringStream(""" { "rootDev": "rootDevValue", "grubDevLabel": "gdlValue", "title": "titleValue", "updateGrubDir": "ugdValue" } """) load(s, result) let config = readConfig() To load a file, simply use a `FileStream` instead of a `StringStream`. Note that the names of the object's fields must match exactly.
Re: nim4Android
Wouldn't it make more sense to bind Nim to Android NDK? I think you would have a hard time to call Android UI libs through jnim, unless you provide a thick layer. There is also [NativeActivity](https://developer.android.com/reference/android/app/NativeActivity.html) which enables you to write purely native apps.
Re: NimYAML 0.7.0 released
NimYAML 0.8.0 is now available. Its focus was on making it more capable of being used for configuration files: * You can now set default values of object fields with `setDefaultValue`. * You can now mark object fields as transient with `markAsTransient` so that they are not serialized or expected in YAML input. * You can now ignore input keys with `ignoreInputKey`. This makes it easier to parse YAML input that contains data which is not of interest. Moreover, timestamps can now be parsed into `Time` values. However, this is only usable with most recent Nim devel version, since timezones are broken in 0.15.2.
Re: Generic openarray param
I wonder why this fails: type Iterable = concept c for i in c: discard proc test[T](x: T) = echo x proc test(x: Iterable) = for i in x: echo i test(1) test([1, 2, 3]) Shouldn't `Iterable` be a better match?
Re: What is "Metaprogramming" paradigm is used for?
I explained some basic metaprogramming stuff in my [article on NimYAML](https://flyx.org/2016/09/22/nimyaml/). Actually, [NimYAML](http://forum.nim-lang.org///nimyaml.org) as a whole is a good example of metaprogramming usage, because what is does is not doable in most other languages (though some „cheat“ by using reflection, which is inferior). [emerald](http://forum.nim-lang.org///flyx.github.io/emerald/) is another project of mine which makes extensive use of metaprogramming. Actually, I initially wrote that to test Nim's metaprogramming capabilities. For snippets, a template usually suffices, you do not need macros for that. It is important to recognize when you do _not_ need macros. The actual use-cases for macros are rather rare, because you should always use the least powerful tool that can do the job, and that mostly boils down to generics and/or templates even for complex problems.
Re: Macro: enumerate exported functions from a module
Wow, I never thought of that. With this, we can write [fuckit.nim](https://github.com/ajalt/fuckitpy)!
Re: Macro: enumerate exported functions from a module
If you write the module yourself, the simplest way would be: macro myMacro(body: typed): typed = # do things here # # do not forget to add the original procs to the output! myMacro: proc proc1*() = discard proc proc2*() = discard # ...
Re: Markdown parser
The Nim compiler has the `rst2html` action which transforms a reStructuredText file to HTML. It can do everything Markdown can, plus some extras (e.g. Nim syntax highlighting). By default, it uses the same HTML template which is being used for generating API documentation (with `nim doc` / `nim doc2`), but you can customize it with a `nimdoc.cfg`. This is somewhat documented [here](http://forum.nim-lang.org///nim-lang.org/docs/docgen.html). The rST implementation is also usable as package from Nim code, as documented [here](http://forum.nim-lang.org///nim-lang.org/docs/rst.html). This forum uses rST as input format for posts.
Re: Is there anyway to change the NimNode(stmt) to string?not the ast format
node.repr
Re: problem when use lua bind
var p = cast[ptr fuck](L.newuserdata(sizeof(fuck).cint)) You allocate memory which is **not zeroed**. So its content may change depending on what it was used for beforehand. echo repr(p) Now you want a representation of that memory. `p.ud` may have any value here. If it is not `nil`, `repr` will try to resolve it to give you a representation of its content. What happens is that after those `echo` s, `p.ud` contains some garbage and `repr` tries to interpret that as a pointer and follows it, resulting in a SIGSEGV. So just move the `echo repr(p)` line after `p.ud = new(test2)`.
Re: Performance of fastRows at module db_sqlite
Yes, Stefan's solution is somewhat nicer, didn't think about that. If there is more data involved, split may be further accelerated by setting `maxsplit`: let (lookup_id, lookup_name_source) = p.rowEntry(col).split('|', 2)[0..1]
Re: Performance of fastRows at module db_sqlite
I cannot really answer the question whether there are missed optimization opportunities in Nim's SQLite wrapper, but being a wrapper, it sounds unlikely. There are some things about your code I can comment on: lookup_id = p.rowEntry(col).split('|')[0] lookup_name_source = p.rowEntry(col).split('|')[1].toUpperAscii() This is inefficient because you are splitting the string multiple times. You can do this instead: let colContent = p.rowEntry(col).split('|') template lookup_id(): untyped = colContent[0] template lookup_name_source(): untyped = colContent[1] But that concerns the CSV and should not be much of a performance hog (unless your CSV is very large). Now the actual part where you could use optimization are these lines: for row in mydb.fastRows(sql"select count(*) from tb_reference_pj where company match ?", (lookup_name_source)): if row[0] != "": What are they for? the result will never be `""`, because `count(*)` always returns some number (correct me if I'm wrong, I haven't done SQL for some time). You are issuing a potentially expensive query here for no reason. Onto the next query: for r in mydb.fastRows(sql"select * from tb_reference_pj where company match ?", (lookup_name_source)): You are querying every column value from a table although you are using only one value afterwards. Okay, to be fair, the following lines are probably not your actual code, right? Note that if you did the template thing I showed, you have to use `lookup_name_source()` here. Your code would probably be faster by just removing the first query.
Re: Nim code to Remove Accented Letters
Here is how you can do it with premature optimization: import unicode, strutils proc translationTable(src, dest: string): array[0x1f00, char] {.compileTime.} = for i in 0..<0x1f00: result[i] = '\0' var srcIndex = 0 destIndex = 0 while srcIndex < src.len and destIndex < dest.len: let srcCh = src.runeAt(srcIndex) if srcCh.int32 >= 0x1f00: echo "Cannot translate this character: " & escape(srcCh.toUTF8()) quit(1) let destCh = dest.runeAt(destIndex) if destCh.int32 >= 0xff: echo "Cannot translate to non-ASCII character: " & escape(destCh.toUTF8()) result[srcCh.int] = destCh.char srcIndex.inc(src.runeLenAt(srcIndex)) destIndex.inc(dest.runeLenAt(destIndex)) proc translate(input: string): string = const ttable = translationTable("ÁÀÃÂÇáàãâçÉÊéêÍíÑÓÔÕñóôõÚÜúü", "CcEEeeIiNOOOnoooUUuu") result = newStringOfCap(input.len) var i = 0 while i < input.len: let r = input.runeAt(i) let t = ttable[r.int] i.inc(input.runeLenAt(i)) result.add(toUTF8(Rune( (t.int8 == 0).int32 * r.int32 + (t.int8 != 0).int32 * t.int32))) echo translate("Cédille Français") Points of interest: * Uses a table that translates unicode characters up to `0x1eff` to ASCII characters. This covers everything up to [Latin Extended Additional](https://en.wikipedia.org/wiki/Latin_Extended_Additional), and I don't believe there are characters beyond that that can meaningfully translated into ASCII characters (but YMMV). * Table is constructed at compile time and is not sparse, so it occupies some 8KB regardless of how many characters you want to translate. On the other hand, there is no _contains_ check necessary which makes the code faster. This is probably only useful if you use the translation code many times during one run. * Implementation uses no branching except for the loop, so it's very fast.
Re: Nim Chess 2 with transposition table support is available
Your compilation instructions would probably be nicer if, instead of depending on absolute paths and symlinks, there would be a Makefile like this: board: board.nim engine.nim nim c -p:../nim-gio/src -p:../nim-atk/src -p:../nim-glib/src -p:../nim-gdk3/src -p:../nim-gtk3/src \ -p:../nim-gtksourceview/src -p:../nim-gobject/src -p:../nim-cairo/src -p:../nim-cairo/src \ -p:../nim-pango/src -p:../nim-pango/src -p:../nim-gdk_pixbuf/src board.nim So that people can simply type make board I can compile it on OSX, but it fails to start with could not load: libgobject-2.0.dylib Not sure why it tries to load that since it is GTK3. Any advice?
NimYAML 0.7.0 released
Since we have Nim 0.15.0 now, NimYAML 0.7.0 follows. This list is relevant for upgrading from a previous version: * The API has been split over several modules. Importing the [base package](http://forum.nim-lang.org///flyx.github.io/NimYAML/yaml.html) imports all subpackages, so this change is backwards-compatible. However, you are encouraged to import only those parts of the API you need. * It is possible to call all loading procs with a `string` instead of a `Stream` input. Loading YAML directly from a string will enable NimYAML to include correct line content in its parsing exceptions. This is not always possible with using Streams, where it will return an empty string instead if the line content is not available. * The API for writing custom represent/construct procs has changed. [representObject](http://forum.nim-lang.org///flyx.github.io/NimYAML/serialization.html#representobject) does not return a `YamlStreamEvent` iterator anymore. Instead, the implementation shall put its generated event(s) into the `SerializationContext`. You have to update existing code if you use that functionality. Major new features are: * The serialization API features better checks and error messages in case of invalid input. This makes NimYAML feasible for user-written configuration files. * Usage of first-class iterators has been removed to make compiling to JS possible. However, finishing this is still blocked by a Nim compiler bug, see [here](https://github.com/flyx/NimYAML/issues/24). * YAML compliance has been improved. A complete list of changes is available [here](https://github.com/flyx/NimYAML/blob/devel/CHANGELOG.md). NimYAML 0.7.0 requires Nim 0.15.0.
Re: about nimscript
What is _code_? An INI file also contains _code_, i.e. some text structure that complies with a grammar. You also need a parser to read it programmatically. You may want to post some references about what's the problem with Python's setup.py, because from what you write, it doesn't seem obvious.
Re: Run tests
You can define any custom commands you want by putting them into `config.nims` at the root of your project. For example, this is what I have in NimYAML: task tests, "Run all tests": --r --verbosity:0 setCommand "c", "test/tests" This basically tells Nim to execute `nim c -r --verbosity:0 test/tests` when I type in `nim tests`. If you want to run tests in multiple files with one command, you can do: task tests, "Run all tests": exec r"nim c -r someFile" exec r"nim c -r anotherFile" setCommand "nop"
Re: Unable to parse JSON Payload
`application/json` is not a supported enctype in HTML. See [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/enctype). There was a [proposal](https://www.w3.org/TR/html-json-forms/) for it - note the giant yellow-dotted banner there. It is not actively maintained and as far as I know, no browser supports it. So your problem is more on the client-side than on the server-side. But even if browsers would support it, this would need to be implemented in Jester, because when the parameters reach your own code, the request has already been parsed. To sum up: Not possible because neither supported on the client nor on the server side. Review your requirements.
Re: Getting captures from PEGS match
> This will work if I use @["", ""] instead, but I don't see why I have to? Because `match` takes an `openarray[string]` for `matches`. It means that the proc works with both an array and a seq. And an array cannot be extended. Since the number of matches in your PEG is statically known, it simply does not make sense to use a seq. Just use an array instead: var matches: array[0..1, string]
Re: Deployment story for Nim
> would the executable be usable in other machines with the same operating > system? In general, yes. > Is it standalone? Depends on your definition of standalone, I guess. For a simple test executable, `ldd` yields: linux-vdso.so.1 => (0x7fff641ee000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x7f0bee51c000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x7f0bee153000) /lib64/ld-linux-x86-64.so.2 (0x564a0afb9000) So apart from the kernel and libc, there are no dependencies. This will of course change when you use non-pure Nim libraries (i.e. libraries that link to a C library). But if your question is whether the executable requires a fully-blown runtime environment (like e.g. JVM or .NET), then the answer is _no_. > What is the standard way to package Nim applications? For source distribution, Nimble. For binary distribution, there is no standard way, since this is very OS-dependent. I guess the sensible way to do it is „use whatever package manager the target OS uses“. Some people like Docker and use that; Nim itself has an official Docker image.
Re: Is this a compiler bug?
I agree that it would be able to determine wether this is a proc call or a type conversion from the parameter type. This can be a feature request. It is probably not so simple to issue a warning with such conflicts, because the type may be defined in one module, the proc in another module, and both get imported to a third module.
Re: Is this a compiler bug?
Where would the compiler bug be? You define a proc named `int`, so when encountering `int(k)`, the compiler tries to call this proc instead of doing a type conversion. I'd say, it behaves as expected. Since types are not keywords in Nim, it is not per se illegal to name a proc `int`.
Re: International Keyboard Setting not mapping correctly in Aporia under Windows
Partly related: I know that GTK's support for Keyboard layouts on Windows is rather broken, because they do not use the API as they should. This has forever been a problem with the Neo layout I use for typing. It is no problem on OSX or Linux. GTK devs marked this issue as _wontfix_. But I am not sure if it is the same problem you encounter.
Re: The cstring type and interfacing with the backend.
> Everything is split more explicitly, and there is no system wide hybrid type > that has to be compatible with whatever the backend is. So, one cstring for `char*`, one for `std::string`, one for `NSString` and one for JS' `string`? That looks like an awful lot of string types.
Re: Nim doc page broken
I created a pull request that fixes this: [https://github.com/nim-lang/packages/pull/408](https://github.com/nim-lang/packages/pull/408)
Re: Where do I learn how to program Nim without a GC?
> I mean somehow I have to tell Nim when to free memory right? Yeah sure, you just use these: [alloc](http://forum.nim-lang.org///nim-lang.org/docs/system.html#alloc,Natural), [dealloc](http://forum.nim-lang.org///nim-lang.org/docs/system.html#dealloc,pointer), [allocShared](http://forum.nim-lang.org///nim-lang.org/docs/system.html#allocShared,Natural), [deallocShared](http://forum.nim-lang.org///nim-lang.org/docs/system.html#deallocShared,pointer). You can cast the `pointer` from and to [ptr](http://forum.nim-lang.org///nim-lang.org/docs/system.html#ptr) types and then you have your manually managed heap memory. (This is a general answer to how to use non-GC'd memory and has nothing to do with memory regions)
Re: Strange GC problem ?
Yeah, if `ref array` does not work properly, it should indeed produce a compiler error. You should file a GitHub issue.
Re: dynamically creating a tuple
As I said, you cannot create a _dynamic_ tuple. The tuple type must be fixed at compile time. I believe you will get better answers if you show example code with an input sequence, and expected output. For me, it is still rather unclear what you are trying to achieve, because when you have a sequence of (int, string) tuples, you already have the tuples you want in there.
Re: dynamically creating a tuple
You cannot have `10` and `'a'` in the same sequence. `10` is an `int`, `'a'` is a `char`.
Re: dynamically creating a tuple
It is not clear what exactly you are trying to accomplish. d = (b: 10, c: "cd") This already creates a tuple and is not a sequence. How does the sequence you talk about look? Since the tuple needs one `int` and one `string`, you would not only need to map the sequence items to tuple fields, but also store `b` as string (or `c` as int if feasible...), because a sequence cannot contain different types. What you want to do is probably possible with a simple generic proc and [fields](http://forum.nim-lang.org///nim-lang.org/docs/system.html#fields.i,T) or [fieldPairs](http://forum.nim-lang.org///nim-lang.org/docs/system.html#fieldPairs.i,T). However: * The transformation would still be static and not dynamic, because you have to give the tuple's type at compile time. * Talking about _dynamically creating a tuple_ hints to a misunderstanding of the purpose of the tuple within Nim's typing system. Transformation between a tuple and a sequence would typically only make sense for data serialization and should be avoided otherwise.
Re: Documentation colour theme
The text I quoted said _consider_. Not _do not use black_. The author considered it and decided to use both black and dark gray text (see the text in the margin and the footer?).
Re: Documentation colour theme
Another opinion on text color from [here](http://forum.nim-lang.org///practicaltypography.com/color.html): > But consider making body text on screen dark gray rather than black. > Screens have more severe contrast than paper, and thus are more tiring to > read at full contrast. This is because screens produce color by emitting > light directly, whereas paper produces color by absorbing and > reflecting ambient light. I would also prefer text color to be a bit darker. But black is overkill.
Re: Going to Haxe. Nim In Action book available.
> I have yet to seen a single example of anybody using namespacing in > functional programming. Then again, its relative "new" in PHP. rofl PHP is all but a functional programming language. I think you are confusing terms here, _functional_ programming languages are things like Haskell, Scheme or (to a lesser extent) LISP. Others provide some functional features in addition to imperative programming. There are lots of programming languages which provide namespaces without being necessarily OOP. Nim itself uses namespaces, which map to filenames (like Python does). Ada has a package system which is the most feature-rich namespace implementation ever, without forcing the user to do OOP. Go uses directories as namespaces. > Yada yada yada ... typical forum bully tactics. I have just answered to your arguments in a critical, but neutral way. This is quite the opposite of _forum bully tactics_, which include, amongst others, [ad hominem](https://en.wikipedia.org/wiki/Ad_hominem) tactics (like, for example, calling another user a _forum bully_). > Lets all wast hours fighting it out on a forum so one of use can both feel > superior. This is not and was never my intent. Where do you deduce this from? Because I criticized your arguments? This is what a discussion is for. If you do not want to discuss, there is no point in answering here. > There is always somebody who gets pissed or disagrees and then wants to wast > hours discussing something that will not change both parties there opinion > anyway. I am not pissed. You seem to be. You even state that later in your post. > Bullshit first class. If you can not tell the different between a piece of > OOP & FP code, then you really do not need to start arguing about it. Feeling > superior yet? As I said, you seem to confuse the term _functional programming_ with _imperative, procedural, non-OOP programming_. I do not want to continue this discussion on a level where you just rely on personal attacks, thanks.
Re: Going to Haxe. Nim In Action book available.
> Is this implying that sufficiently large codebase of any other (or of a > specific programming language) would look any better? I don't think so, but > i'd like to hear about that. Almost all codebases of large applications look awful. There are a lot of reasons for that other than programming paradigms used. I do not want to claim that some would look better without OOP. I simply wanted to state that I had a look at a lot of code bases through the years in order to find evidence of how OOP would lead to cleaner code, and I have yet failed to find any.
Re: Going to Haxe. Nim In Action book available.
> In general object oriented programming results in a more clean code base ( > example ). Have you ever seen any codebase of a sufficiently large Java library/application? I have yet to see _one_ example where OOP lead to a cleaner code base. [This image is usually a pretty accurate description of an OOP codebase](http://forum.nim-lang.org///imgur.com/Q0vFcHd). > Personally i do not understand why people still insist on functional > programming. Nobody suggested functional programming. > Both do the same in this simple example. And none is functional. > But as one starts to extend functionality, its where you are much more likely > to run into conflicts ( forcing the need for instance to namespace ). Namespaces have nothing to do with object orientation. You can perfectly use namespaces in non-OOP languages. > Of the two examples, what is more easy to extend ( inherit, override, > abstract, etc ) and clean. Its simply the object oriented version. So you show some OOP code, then you show some imperative, non-OOP code, and then you ask which is more easy to _inherit_, _override_, make _abstract_? Well, those are all things you do in OOP languages, and you just assume that this is useful and needed without providing any evidence for it. So tell me: How would you want to extend a _round_ function, so that OOP becomes useful? The only useful extension is to be able to use it on other types than just `float` \- and that can easily be done with generics and without OOP. And um, calling this messy `class Main {` stuff _clean_ is… nothing I would do. > If we simply look at GoLang with its forced function paradigm, it still > relies on C like function attachment to objects. Go is not functional, it is imperative. I also do not understand what exactly you mean by „C like function attachment to objects“. You seem to assume that it is necessary to attach functions to objects, without providing any evidence for it. > Nim really focuses more to Python developers. Where Crystal really focused on > Ruby developers. I do not think Nim focuses on Python developers at all. It shares some syntactic constructs with Python, but it is very different. Crystal, on the other hand, seems indeed to be very focused on Ruby devs.
Re: Execution speed Nim vs. Python
cblake: C11 made VLAs an optional feature though. I consider C VLAs a very poor solution; as you say, it's mostly syntactic sugar for alloca. And yes, something between array and seq would be nice. But currently, Nim's type system does not allow a type with a runtime-calculated length parameter. Allowing it would be a hack similar to C VLAs.
Re: Execution speed Nim vs. Python
Stefan_Salewski: > May it be possible to have one single Seq in each proc on the stack? Of > course it has to be the last element, and can only work when that proc do not > call other procs. That may be possible, but far too complicated with far too few impact on performance. The compiler would need to properly place the seq, statically analyze that no other procs are called, and add special transformation code every time you copy this seq. If you have, somewhere in your proc, some code `a.b`, where `b` is some field in `a``s type, and you transform ``b` into a getter proc at some point in the future, you code suddenly wouldn't be able to compile anymore. And this is just one example why it is a really bad idea. Ada is the one language I know which went a long way for arrays of dynamic length which can still be stored on the stack. The only restriction is that an array cannot change size after initialization. Therefore, it does not cover all use cases and it still needs dynamic container types in its standard library. Also, handling those arrays is a bit more difficult than in other programming languages. Everything comes at a price.
Re: Execution speed Nim vs. Python
> I do not understand the use of the openarray parameter in relation to > performance. `openarray` has nothing to do with performance. It is just a feature to allow implementing procs that take both an `array` and a `seq` as parameter. The actual performance gain stems from using arrays instead of seqs. Because an array's length is known at compile time, it can be allocated on the stack. Seqs always need to be allocated on the heap. Therefore, it is always advisable to use arrays when possible. Other performance optimizations are explained in the previous posts. > If the length of the output array of a proc is not known in advance, are > there general rules to accomplish a good performance? If you can calculate the target length of the array efficiently before actually filling it, initialize the result seq with as many elements as needed (as shown in the other posts) or use `newSeqOfCap` if you're on devel or once this has made it into a release.
Re: spawninig of more than 8 threads problem
Well, I'm done with ideas. If you want to investigate further, I guess gdb or lldb would be able to help you see what's happening.
Re: spawninig of more than 8 threads problem
On second thought, the scheduler may be intelligent enough not to start more than one thread if it knows that they all wait for the same resource. But I wouldn't assume it.
Re: spawninig of more than 8 threads problem
Well it works for me with 32 characters in the string (Linux, 4 CPUs). So it seems to depend a bit on the OS - and therefore, the scheduler. > I think this shouldn't be the case. I'll try to explain what might happen. I do not know all internals involved, so it may or may not be accurate. Suppose all the threads have been started and we are at some point _x_ where one thread just finished writing its character. That thread releases the lock, and the scheduler sees „ah, the lock has been released, I have a bunch of threads waiting for that, let's wake the next in line. And because I have multiple CPUs, let's directly start multiple threads.“ The next thread in line - lets call it `T1` \- executes and acquires the lock. Unfortunately, it is not the thread that can write the next character. So it releases the lock and goes to sleep for 1ms. Meanwhile, another thread (`T2`) has been started and tries to acquire the lock again, but `T1` is still holding the lock. So `T2` tells the scheduler it is still blocked by the lock and goes to sleep again. The scheduler moves it to the back of the queue of blocked threads. Now, unfortunately, `T2` is actually the thread that can write the next character. But the scheduler will now execute all the other threads first. Then, if you're lucky, `T2` will finally be executed because all other threads currently sleep. This, however, will only happen if the scheduler can make all the necessary context switches between threads, all the executions and sleeps etc, in less than 1ms (the time the other threads sleep). Depending on your system, that may or may not be enough time (I do not have the metrics on context switches at hand, so I can only guess). If a round-trip through all the threads takes more than 1ms, it can happen that `T2` is blocked again by another thread when it is its turn to execute. And the same circle happens again. So it cannot be guaranteed that `T2` will ever be executed while the lock is acquirable by it. You may try to increase sleep time. But all in all, this code is outright horrible because of those interdependencies, and you should never do something like that in production code.
Re: spawninig of more than 8 threads problem
The problem is that threads _go to sleep while still holding a lock_. Well, the real problem is that afaik there is no guarantee that this code will ever finish, because the scheduler is not required to ever wake the right thread when a bunch of other threads are still waiting. But anyway, Moving the `sleep` call behind the lock seems to work fine in practice: import unicode, threadpool, locks, os proc lenU*(s: string): int = result = s.runeLen proc charAtPosU*(s: string, pos: int): string = assert(pos >= 0 and pos < s.runeLen) result = s.runeAtPos(pos).toUTF8() proc multithreadedPrint(sMsg: string, nCount: int) = var nLen = sMsg.lenU nCallsTotal = 0 nCallsCur = 0 lk: Lock res = 0 proc worker(c: string, value: int) {.gcsafe.}= while true: var found = true acquire(lk) try: if nCallsCur == nCallsTotal: return if res == value: inc res res = res mod nLen inc nCallsCur stdout.write c else: found = false finally: release(lk) if not found: sleep(1) if nLen > 0: if nLen > MaxDistinguishedThread: echo "Your string is too long. Maximum allowed is ", MaxDistinguishedThread, "!" return setMinPoolSize(nLen) setMaxPoolSize(nLen) initLock(lk) try: nCallsTotal = nLen * nCount echo("Total threads: ", nLen) echo("Total calls: ", nCallsTotal) for i in 0..
Re: TaintedString.parseInt problem
@luntik2012: From documentation of `execProcess`: > WARNING: this function uses poEvalCommand by default for backward > compatibility. This means that it executes the command within a shell, which is probably responsible for the trailing newline. @Stefan_Salewski: Well, it's easy enough to implement: import strutils, future proc hexDump(s: string) = echo lc[toHex(int8(c)) | (c <- s), string].join(" ") hexDump("123\n") yields: 31 32 33 0A
Re: TaintedString.parseInt problem
The problem is that the result of `execProcess` contains trailing whitespace (a newline in this case). Try: return execProcess(command & "" & filepath & ) / 1000""").strip.parseInt
Re: Inline ASM
Look [here](http://forum.nim-lang.org///nim-lang.org/docs/manual.html#statements-and-expressions-assembler-statement).
Re: Nim how to write plug-ins to achieve dynamic loading?
Compile your plugins with `--app:lib`, then use the `dynlib` module in the main program to load them at runtime.
Re: How do I pass an operator as proc parameter?
Usually, you would define `action` as `proc(l,r: T): T`. But this does not work for `xor` because of this paragraph in the manual ([see also](https://github.com/nim-lang/Nim/issues/2172)): > Assigning/passing a procedure to a procedural variable is only allowed if one > of the following conditions hold: > > * The procedure that is accessed resides in the current module. > > * The procedure is marked with the procvar pragma (see procvar pragma). > > * The procedure has a calling convention that differs from nimcall. > > * The procedure is anonymous. `xor` is not in the current module, not marked with `{.procvar.}`, has the calling convention `nimcall` and is not anonymous, so it may not be passed to a procedural variable. You can, however, use a template: template bitWise*[T](buff: openArray[T], action: untyped, mask: openArray[T]): seq[T] = var result = newSeq[T]() for i in 0..
Re: Dynamic Object Type Fields
This is not possible by design. type test* = object Here, you declare an object that has no fields. var t = test() Here, you instantiate this object. `t` has the type `test`. var t.name = "kek" The compiler now looks at `t`'s type and sees that this type has no field `name`, and thus quits with an error at compile time. If you want to allow that, that means that every construct `t.someFieldName` would not be allowed to fail at compile time (because that field may be added dynamically). So the compiler can no longer guarantee that the field you try to access exists. That's the difference between static and dynamic typing systems. The question is: Why do you think you need it?
Re: Opengl vertices
The OpenGL wrapper provides a `GLvectorf3` type, why don't you use that? Also, you should show more of your code for us to see what you are actually doing.
Re: Convert seq into tuple
> I hope I'm wrong and there is an elegant way to define a large tuple. What do you need a tuple this size for? Your problem is likely that you use the wrong tool for the job. The need to write var myTuple: tuple[a00,a01,a02,a03,a05 ... a98,a99: int] roots from the nature of the tuple type. If you do not want to do that, you likely do not want to use a tuple.
Re: gensym pragma with names of entity passed as template parameter not working as expected
You cannot `gensym` the pragma since it is injected as parameter. But you can simply enclose the template body in a block: template foo(txn, body: untyped): untyped = block: let txn = 1 body foo hello: echo hello foo hello: echo hello
Re: Convert seq into tuple
proc fillTuple[T: tuple, V](target: var T, input: openarray[V]) = var index = 0 for field in target.fields: assert input.len > index field = input[index] inc(index) var myTuple: tuple[a,b,c: int] fillTuple(myTuple, @[1, 2, 3]) Or, if you want the tuple as return value: proc fillTuple[T: tuple, V](input: openarray[V]): T = var index = 0 for field in result.fields: assert input.len > index field = input[index] inc(index) var myTuple = fillTuple[tuple[a,b,c:int], int](@[1, 2, 3])
Re: macro changing type of const literals not working
Works for me on devel. However, the bit with the `include` does not.
Re: [macro] Adding echo to a function
import macros macro addEcho(s: untyped): stmt = s.body.add(newCall("echo", newStrLitNode("OK"))) result = s proc f1() {.addEcho.} = let i = 1+2 echo i You have to use untyped because with stmt, Nim seems to create a symbol f1 beforehand and then gets confused about it because you return a proc f1 again with the same signature. This should probably be reported as bug, because it should at least generate a sensible error message.