Re: a small change to macros.getCustomPragmaVal

2018-09-29 Thread timothee
looks like original code was buggy indeed, could you send out a PR?


Re: the Fibonacci benchmark

2018-09-29 Thread cblake
It might be a lot of things, but I'm telling you - there is a `gcc` 
optimization, very finicky about context (and probably compiler flags, too), 
that reduces function calls by almost exactly his speed-up factor. There's 
really no need to guess if I'm right, though. Just add `-pg` to the gcc flags 
(in both cases), run `gprof` on the output, and count funcalls in both cases to 
confirm.


Re: the Fibonacci benchmark

2018-09-29 Thread mratsim
Besides constant folding, there might be [code 
alignment](https://dendibakh.github.io/blog/2018/01/18/Code_alignment_issues) 
that can cause massive perf difference.


Re: zsh auto-completion

2018-09-29 Thread zeegroen
Alright, so after looking around a bit, I figured how to do it. It's not that 
complicated, but for the sake of future readers, I will write it down here for 
oh-my-zsh:

  1. install zsh completions as detailed in 
[https://github.com/zsh-users/zsh-completions](https://github.com/zsh-users/zsh-completions)
  2. in your nim installation, you will find the file 
"nim/tools/nim.zsh-completion"
  3. copy this file to the plugins folder of zsh-completions under 
"~/.oh-my-zsh/custom/plugins/zsh-completions/src/"
  4. rename that file to "_nim"



It should work then!


Re: collections of procs[T]()

2018-09-29 Thread mitai
Thank you!

this does work:

> 
> type
>   Data*[T] = object
> contents: T
> subscribers: seq[proc(d: T)]
> 
> proc createData*[T](t: typedesc[T], c: T): Data[T] =
>   result = Data[T]()
>   result.contents = c
>   result.subscribers = @[]
> 
> proc addSubscriber*[T](d: var Data[T], cb: proc(d:T)) =
>   d.subscribers.add(cb)
> 
> proc callSubscribers[T](d: T) =
>   for n in d.subscribers:
> n(d.contents)
> 
> var dd = createData(string, "data")
> proc print[T](d: T) =
>   echo $d
> 
> dd.addSubscriber(print)
> 
> dd.callSubscribers()
> 
> 
> Run


Re: the Fibonacci benchmark

2018-09-29 Thread cblake
No `gcc` doesn't -- at least not for me with a factor of about 7X, almost 
identical to @adrianv 's results. I used both an earlier gcc-7 and a gcc-8.2 
just now.

If you don't want to disassemble your binary, that's ok. You can check this 
with `gcc -pg` and `gprof` which will count calls for you.

I also gave a complete example in C that does the optimization I mention in the 
prior thread which I will reproduce here because the new forum code hides it 
behind "load more posts". With `fib(30)` I get 118793 calls. With `fib(40)` I 
get 14612525 calls. With even a low `fib(20)` I get 950 calls. Does 950 calls 
seem like compile-time calculation to you? With `fib(46)` I get 262211393 calls.


#include 

float fibonacci(int x) {
return x < 2 ? (float)x : fibonacci(x - 1) + fibonacci(x - 2);
}

void NimMainInner() {
printf("%.0f\n", fibonacci(46));
}
int main() {
#ifdef FIB_SLOW
NimMainInner();
#else
void (*volatile inner)(void) = NimMainInner;
inner();
#endif
return 0;
}


Run

If one simply calls `NimMainInner()` directly instead of through the volatile 
function pointer `inner()`, `fib(20)` generates 10942 calls instead of 950.

I understand my example uses floating point, not integer arithmetic, but 
@adrianv 's numbers make it sure seem like the same situation. @adrianv can 
also compile with `-pg` and run `gprof` to check. Or he could adapt this C and 
compile it the same way his `nim.cfg` or whatever compiles his Nim generated C.

I'm not quite sure what more evidence you would require. It isn't hard to 
calculate how many function calls doubly recursive Fibonacci requires.


Re: the Fibonacci benchmark

2018-09-29 Thread Hlaaftana
Nim doesn't evaluate fib(46), GCC does. And it doesn't get up to fib(46), it 
evaluates up to fib(34) then does the remaining calculations at runtime. I'm 
sure this exact same occurence was mentioned in an older thread.


Re: collections of procs[T]()

2018-09-29 Thread LeuGim

proc addSubscriber*[T](d: var Data[T], cb: proc(d:T)) =
  d.subscribers.add(cb)


Run

A typo `T` for `Data[T]`, and `var` needed for `add`.


Re: the Fibonacci benchmark

2018-09-29 Thread cblake
I am not quite sure what "original" benchmark you mean - perhaps the 4.6 s for 
Nim vs 6.0 s for C on the original github page at the top of this thread. That 
may be small scale code layout/caching/branch predictor effects as you say.

However, the difference in this thread of 8X is _almost certainly not_ 
compile-time evaluation of fib(46), nor a coincidence, nor some generalizable 
Nim is effectively faster than C { though ;) is noted! :-) }. Compile-time 
evaluation would likely be many thousands of times or more faster than that - 
faster even than the memoized/linearized versions of the calculation which are 
already O(1000x) faster. Indeed, one gets "too many iterations" trying to 
`const x = fib(46)` from the Nim VM.

The merely ~8X faster observed twice in this thread is something else which I 
have already explained in the prior thread and in this thread linking to that. 
And that explanation/approach does generalize a little, and even across 
programming languages. Certain iterative/recursive code that does very little 
work like simple adds or swaps { permutations, I'm looking at you :-) } can 
often be sped up by either manually or automatically unpacking/unrolling the 
last few recursions so that more work is done on a per-function call basis or 
said otherwise there are fewer function calls.


Re: Nim alternative to "With" in VB.Net and other basic dialects

2018-09-29 Thread kcvinu
Yes. Thats right. But its a dependency. My gui lib already depend upon winim. 
At first my objects were like this - "control.property.text" But i have changed 
that into this - "control.text"


Re: the Fibonacci benchmark

2018-09-29 Thread zahary
Don't get overexcited. This is probably just a coincidence coming from the 
random addresses of the compiled functions and branch instructions that affect 
things like the branch prediction unit in the CPU.


Advice Module Publication

2018-09-29 Thread geezer9
I am close to being able to publish yet another graphical interface module for 
nim. It will sit on top of oldwinapi or gtk2 and be philosophically similar to 
iup. I am currently developing it (on Ubuntu) using a local GIT repository 
which is in my working directory and pushing versions of the module using 
**nimble install** so they end up in my user's home .nimble directory.

Once I publish this (hopefully on Github), how do I keep the nimble package 
separate from the development respository - so the module can be used without 
needing to dig through the development files.

Pointers to tutorials on publishing nim modules would be appreciated as I have 
not published software before. 


Re: Version 0.19.0 is out

2018-09-29 Thread DTxplorer
Thanks to all contributors !


Nim beginners tutorial

2018-09-29 Thread miran
A new version of [Nim basics](https://narimiran.github.io/nim-basics) tutorial 
is out.

It uses Nim 0.19.0, meaning sequences and strings are automatically initialized 
so we don't have to do it explicitly. (But there is a note for users of older 
Nim versions)

And if you haven't seen it in the last month or so: there is also a slight 
redesign, so now the content is a bit prettier :)

* * *

If you find any errors, things that could be improved, etc. please let me know 
— either write it here or open an issue [in the 
repo](https://github.com/narimiran/nim-basics).


Re: the Fibonacci benchmark

2018-09-29 Thread dom96
> If Nim compiles to C Nim is not faster than C but Nim is able to produce 
> faster C code than human programmers.

Effectively making it faster than C ;)


Re: collections of procs[T]()

2018-09-29 Thread mitai
Thankyou for your reply @mratsim

I tried the following:


type
Data*[T] = object
  id: string
  contents: T
  subscribers: seq[proc(d: T)]
  
  
  proc addSubscriber*[T](d: T, cb: proc(d:T)) =
d.subscribers.add(cb)
  
  proc callSubscribers[T](d: T) =
for cb in d.subscribers:
  cb(d.contents)
  
  var dd = Data[string]()
  dd.contents = "a content"
  dd.id = "1"
  dd.subscribers = newseq[proc(d: string)]()
  dd.addSubscriber(proc(d: string) = echo $d)
  
  dd.callSubscribers()



Run

> but I get this error:


  testproc.nim(19, 3) Error: type mismatch: got 
  but expected one of:
  proc addSubscriber[T](d: T; cb: proc (d: T))
first type mismatch at position: 2
required type: proc (d: T){.closure.}
but expression 'proc (d: string) = echo [$d]' is of type: proc (d: 
string){.gcsafe, locks: 0.}
  
  expression: addSubscriber(dd, proc (d: string) = echo [$d])


Run

it seems I'm missing something


Re: the Fibonacci benchmark

2018-09-29 Thread cblake
I also got `nim c` 's code running twice as fast as `nim cpp` 's code. See some 
previous discussion: 
[https://forum.nim-lang.org/t/1779](https://forum.nim-lang.org/t/1779) \- there 
are cases where Nim's generated C code "inspires" the C compiler to "unroll the 
last few recursions" and save 4x or 8x or maybe even 16x depending the number 
of funcalls (depending on the unroll amount). It's not quite constant folding. 
disassembly and looking for `callq` can be helpful here.

I think the result is correct by the more old school definition starting from 
"1 1 2 3 5" (with indexing starting at zero), not "0 1 1 2 3 5" as per 
[https://en.wikipedia.org/wiki/Fibonacci_number](https://en.wikipedia.org/wiki/Fibonacci_number)
 { or maybe the indexing is not what @miran expects, but he uses a ";-)" }. 
Anyway, there is sort of "more than one right answer" in a couple of ways 
depending on index origin or 0 inclusion.


Re: the Fibonacci benchmark

2018-09-29 Thread miran
On my end `nim cpp` is twice _slower_ than `nim c`.

Oh and btw, whichever version of code you use — the result is not correct ;) 
Try running `fib(2)` and you'll see what I'm talking about.


zsh auto-completion

2018-09-29 Thread zeegroen
Hi y'all,

I see in the codebase that there is an auto-completion feature for zsh, but it 
doesn't seem to automagically work after installing nim through Solus's package 
manager: 


sudo eopkg install nim


Run

(with eopkg being the standard package manager on Solus, cfr. "apt"). What else 
should I do to get the auto-completion feature?

Thanks in advance!


Re: the Fibonacci benchmark

2018-09-29 Thread DTxplorer
If Nim compiles to C Nim is not faster to C but Nim may produce faster C code 
than human programmers.


Re: the Fibonacci benchmark

2018-09-29 Thread Hlaaftana
I think this was posted a while ago and the answer was that G++ found a way to 
constant fold Nim's C++ output. This means it probably evaluated fib(46) before 
the program ever ran. A bit disappointing, sure, but the C output benchmark is 
still very good.


the Fibonacci benchmark

2018-09-29 Thread adrianv
Hi, on twitter I saw that Nim performed better on fibonacci benchmark than C 
and C++ ([https://github.com/drujensen/fib](https://github.com/drujensen/fib)) 
and wondered why. I did my own tests and these are quite interesting:Language| 
Time in s| compiled with  
---|---|---  
Nim| 0.456| nim cpp -d:release fib.nim  
Nim| 3.845| nim c -d:release fib.nim  
C++| 3.843| g++ -O3 -o fib fib.cpp  
C| 3.902| gcc -O3 -o fib fib.c  
  
why in the world is the Nim version compiled so much faster ?

then I tried a slightly different version of Nim code


proc fib(n: uint64): uint64 =
  if n > 2.uint64 : return fib(n - 1) + fib(n - 2)
  return n


echo fib(46)


Run

Language| Time in s| compiled with  
---|---|---  
Nim| 0.450| nim cpp -d:release fib.nim  
Nim| 3.209| nim c -d:release fib.nim  
  
its nice to see Nim to perform so well here - but why is the gap between the C 
and CPP compilation for the same code? 


Re: Nim hashtable mapping strings to any type

2018-09-29 Thread mratsim
That was something that was in the manual as coming soon for about eight months 
before being removed:

[https://github.com/nim-lang/Nim/commit/c671356d51488c96b4749a4d109b00d924e1f739](https://github.com/nim-lang/Nim/commit/c671356d51488c96b4749a4d109b00d924e1f739)

This should still be happening but after concepts, generics, statics are more 
consolidated. The goal is not to interop with C++ inheritance though, but you 
can already use `importcpp` for that.


..
  VTable types
  
  
  Concepts allow Nim to define a great number of algorithms, using only
  static polymorphism and without erasing any type information or 
sacrificing
  any execution speed. But when polymorphic collections of objects are 
required,
  the user must use one of the provided type erasure techniques - either 
common
  base types or VTable types.
  
  VTable types are represented as "fat pointers" storing a reference to an
  object together with a reference to a table of procs implementing a set of
  required operations (the so called vtable).
  
  In contrast to other programming languages, the vtable in Nim is stored
  externally to the object, allowing you to create multiple different vtable
  views for the same object. Thus, the polymorphism in Nim is unbounded -
  any type can implement an unlimited number of protocols or interfaces not
  originally envisioned by the type's author.
  
  Any concept type can be turned into a VTable type by using the ``vtref``
  or the ``vtptr`` compiler magics. Under the hood, these magics generate
  a converter type class, which converts the regular instances of the 
matching
  types to the corresponding VTable type.
  
  .. code-block:: nim
type
  IntEnumerable = vtref Enumerable[int]
  
  MyObject = object
enumerables: seq[IntEnumerable]
streams: seq[OutputStream.vtref]

proc addEnumerable(o: var MyObject, e: IntEnumerable) =
  o.enumerables.add e

proc addStream(o: var MyObject, e: OutputStream.vtref) =
  o.streams.add e
  
  The procs that will be included in the vtable are derived from the concept
  body and include all proc calls for which all param types were specified 
as
  concrete types. All such calls should include exactly one param of the 
type
  matched against the concept (not necessarily in the first position), which
  will be considered the value bound to the vtable.
  
  Overloads will be created for all captured procs, accepting the vtable 
type
  in the position of the captured underlying object.
  
  Under these rules, it's possible to obtain a vtable type for a concept 
with
  unbound type parameters or one instantiated with metatypes (type classes),
  but it will include a smaller number of captured procs. A completely empty
  vtable will be reported as an error.
  
  The ``vtref`` magic produces types which can be bound to ``ref`` types and
  the ``vtptr`` magic produced types bound to ``ptr`` types.


Run


Re: collections of procs[T]()

2018-09-29 Thread mratsim
Yes you can, see this for example: 
[https://github.com/mratsim/nim-rmad/blob/master/src/autograd.nim#L46-L57](https://github.com/mratsim/nim-rmad/blob/master/src/autograd.nim#L46-L57)

Note that the proc arity (number of arguments) is part of the type, as is its 
calling convention (pointer/{.nimcall.} vs {.closure.}).