Re: How to use private variables when you put all types in one module

2019-12-18 Thread treeform
I don't think private variables on structs are worth it in general. I almost 
make everything public by default. I don't export low level functions though...


How to use private variables when you put all types in one module

2019-12-18 Thread kcvinu
Hi all,
Nim experts says that if you faced recursive module dependency, you just 
put all your types in one module and import it to use in another modules. So 
this is my question. If you did so, how could you manage private properties ? 
If you add a star sign, it will be public and exported, but if you don't, then 
it is not visible in your module. I hope somebody can help me. Thanks in advance


creating a enum type after calling a macro on various modules

2019-12-18 Thread mrgaturus
Hi again, i want to create a final enum after calling a macro that define a 
group with actions on various modules, something weird is that i need import 
the module where the enum is generated before other modules are imported, is 
there a way for create a macro that will be called after the group macro is 
called on every module?, Here is an example of what I mean: 


# Module where is the macro
# Actually is implemented using const by incrementing a compileTime var
from builder import group

# Module A
# Module A imports this module before Module B and Module C is imported
group Window:
  Maximize
  Minimize
  Close
  FocusIM
  UnfocusIM

# Module B
group SubWindow:
  Elevate
  Resize
  Move

# Module C
group Color: discard
group Layers: discard

# Final Type, generated here, using other macro
type
  Groups = enum
gWindow
gSubWindow
gColor
gLayers
  GroupsSet = set[Groups]


Run


Re: What’s your favorite programming language and why?

2019-12-18 Thread kcvinu
HLA website contains some very good books about win api programming. I once 
tried to install HLA but for some reasons, it was not worked in my system. 
There was no way for communication without a forum. 


Re: What’s your favorite programming language and why?

2019-12-18 Thread kcvinu
Hey, how do you create exe files from Kotlin source code ? 


Re: What’s your favorite programming language and why?

2019-12-18 Thread kcvinu
  1. Visual Basic.Net - For easiness
  2. AutoIt - For power & convenience
  3. Nim - For elegance, fun
  4. D
  5. Go




Re: Preview of Weave/Picasso v0.1.0, a message-passing based multithreading runtime.

2019-12-18 Thread rayman22201
It's similar to the Rayon or Tokio libraries from Rust.

Weave provides a set of fundamental building blocks to create safe and high 
performance multi-threaded programs.

Anyone who wants to write multi-threaded programs in Nim should be very excited 
about this.

like Rust, Nim itself provides a minimal runtime (as it should be for systems 
languages), and allows libraries to provide fundamental features without 
modification of the compiler.

This is actually a core philosophy of Nim. It has a small core but allows for 
large extensions (mainly through macros and a few other features.)


Re: Nim In Action worth it with 1.0

2019-12-18 Thread SolitudeSF
[https://www.reddit.com/r/nim/comments/df2t60/nim_in_action_worth_it_with_10](https://www.reddit.com/r/nim/comments/df2t60/nim_in_action_worth_it_with_10)/
 another bot


Re: Introducing Synthesis: a Finite State Machine generator

2019-12-18 Thread rayman22201
@mratsim. You are awesome as always.

Since the state machines can be nested, I wonder if this could be used to 
facilitate a heap free (and possibly stack free) async implementation, suitable 
for embedded.

hrmm :-)


Re: Preview of Weave/Picasso v0.1.0, a message-passing based multithreading runtime.

2019-12-18 Thread kobi
Sorry, my question was basically: what does the word runtime mean? Does it 
replace certain operations in the executable that the Nim compiler produces by 
default, in that case, it's a low level integration with Nim, the compiler. So, 
what do the users need to do to use this multithreading runtime. It's likely 
I'm just misunderstanding everything. But could be that other nim users would 
be more enthusiastic when they understand what your project means. Thanks


Nim In Action worth it with 1.0

2019-12-18 Thread HudsonJon
I'm thinking about getting a book about Nim... and as you all know there's only 
one. Nim In Action has been out a while; is it directly relevant to the 1.0 
release? Does 1.0 have anything missing from the book?

Would you recommend it?


Editor support for Nim 1.0 ?

2019-12-18 Thread ConnorEzra
Hello.

I was tinkering with Nim in the past already and wanted to check out the 1.0 
version. Unfortunately, plugins for almost all editors lags behind - I know 
that 1.0 is just 4 days old, but it seems that even 0.19.6 release doesn't have 
wide editor support. It looks like only Emacs (and maybe NPP) plugin is 
actively maintained.

Maybe I'm missing something obvious... In what editor are you writing Nim today?

Best regards 


Nim is the friendliest language to start ?

2019-12-18 Thread CarterJohn11
I've been around writing relatively large applications in mainstream languages 
as well as personal projects in languages like Erlang, Ocaml, Rust, and Scheme. 
To sum it up, I'm a PL aficionado.

It is very mandatory today that a good programming language is 50% about good 
tooling and ecosystem. For instance, I love Ocaml, but it's 2020 and it still 
doesn't own a native concurrent construct and its barrier to entry is too high 
for busy programmers to spend time learning it. A lot of great languages die 
because they don't have a straightforward path to success and small wins to 
warrant users' productivity loss.

My go-to language is almost always Go. It's not a great language by itself, but 
most of my work is about building API servers and its tooling is just very 
robust and frictionless. Also, it takes little effort to type in Go (at least 
for me) and the error messages are very debug-friendly.


Re: What’s your favorite programming language and why?

2019-12-18 Thread cantanima
**preface** My priorities are safety, legibility, and expressiveness, in that 
order. I can program in C and C++, but I much prefer _readable_ languages where 
the compiler identifies as many errors as possible before you run it, because 
debugging sucks, and debugging languages that thinks safety and readability are 
signs of weakness is... better left unsaid.

_Languages I like_ (in alphabetical order)

**Ada** : C++ has spent 30+ years trying unsuccessfully to make C as featured 
_and safe_ as Ada 83 (exceptions, generics, multitasking, ability to write 
large, nontrivial programs without pointers, modules, ... oh, wait, C++ _still_ 
doesn't have modules, and on and on...) while still looking like C, because `a 
= (b < c) ? d : e;` is so much more desirable than `a := (if b < c then d else 
e);` or something. Ada 95 was the first ISO-standardized language with 
object-oriented features. Ada 2012 has Design By Contract. A dialect of Ada 
called SPARK offers the ability to prove a program meets specifications laid 
out in DBC and/or pragmas. When Ada came out, people objected that it was too 
complicated, so today we program with even more complicated languages that 
offer fewer features, and no one knows Ada still exists and probably powers the 
airplane you flew to that last FLOSS conference, so companies cannot find Ada 
programmers, so they are switching to other languages which are less safe but, 
hey, the kids coming out of universities these days don't like reading and 
would rather match curly braces, so what can we do? (Yes, I have heard kids 
coming out of universities say that they don't like languages that don't use 
curly braces, with no further reasoning on the matter.)

**Kotlin** (please don't kill me): A better Java than Java. Lots less 
boilerplate. Free & great tooling. The use of `in` and `out` types for 
generics. A serious and almost successful attempt at `null` safety. I only 
learned Kotlin because the choices in Android Studio are Java and Kotlin, so I 
decided to try Kotlin I've never gone back to Java. Kotlin Native may or may 
not turn out to be a thing one day, too.

**Modula-2** : Like others, I learned with Pascal; Modula-2 was Wirth's systems 
programming language, and back in the early 90s the only options I had on an 
Amiga were Modula-2, Oberon-2, and C. I couldn't find learning material on 
Oberon (really) so Modula-2 it was. It was elegant, powerful, and -- given the 
options -- the safest language available.

**Modula-3** : Modula-3 was from DEC, inspired by Modula-2 but different. 
Surprisingly good, frustratingly boneheaded at times (you have to jump through 
far too many hoops to instantiate a generic modules), but whenever I finished 
writing a Modula-3 program, I always felt as if I'd had fun and wanted to do 
more.

**Nim** : Do I have to explain this on a Nim forum?

_Language that was a sore disappointment_ (not asked, but some people are 
writing this anyway)

**Oberon** : [Not to be confused with Oberon-2, which is similar] In principle 
there's a lot to like, but after working through much of Wirth's Compiler 
Construction textbook with Oberon I found myself increasingly frustrated by 
choices that were made for the compiler writer's convenience, even when they 
wouldn't have cost much. Maybe it was unfair because by the time I learned 
Oberon I'd learned a lot of other OO languages, but, for instance:

  * There is no way to initialize an object automatically; you must always 
manually initialize, e.g., `o := NEW(T); o.Init;`
  * Arrays of unknown size are allowed only as parameters to procedures, and 
you cannot allocate an array whose compile-time size is not known except 
through gruesome hacks. That is, you can do `TYPE T=ARRAY 10 OF INTEGER; VAR a 
: POINTER TO T; BEGIN a := NEW(T); END` but not `TYPE T=ARRAY OF INTEGER; VAR a 
: POINTER TO T; BEGIN a := NEW(T, 10); END` or something similar. Some Oberon 
fans claim this defect is evidence of the language's brilliant design, but it's 
important enough that at least two compilers I examined introduced a 
`SYSTEM.NEW` command to do this... and each implemented it differently.
  * In an attempt to minimize the language, some machine-level commands are in 
the language proper, such as `LSL` and `ASR`, but others are consigned to the 
`SYSTEM` module, which you are warned to avoid if you want to write portable 
programs. In particular, masking an `INTEGER` requires you to convert it to a 
`SET` via `SYSTEM.VAL`, use the `*` operator with another `SET`, then convert 
back. All this just to avoid using the `&` operator on integers?
  * Speaking of which, why `&` instead of `AND`? After all, `OR` gets its own 
keyword. What happened to the aim of readability?
  * In the command `o.method()`, `o` is not automatically passed to `method()` 
as an argument, so you have to write `o.method(o)`, which grows really tiresome 
after a while, especially if you use name variables according to their purpose 
rather than 

Re: Walking trees without recursive iterators

2019-12-18 Thread cblake
That sounds like a bug/limitation in @sschwarzer's algorithm to me, but maybe 
he can verify. Good catch, @e.

Another pretty different approach that I use in `cligen/tern.nim` (that does 
not support in-iteration deletion) is something like this: 


const NUL* = '\0'
type
  NodeOb*[T] {.acyclic.} = object
ch*: char
cnt*: int
when T isnot void: val*: T
kid*: array[3, ref NodeOb[T]]   #0,1,2 ~ <,=,>
  Node*[T] = ref NodeOb[T]
  Tern*[T] = object   ## A Tern can be used as either a mapping from strings
root*: Node[T]## to type ``T`` or as a set(strings) if ``T`` is 
void.
count: int## Number of elements
depth: int## Depth of Tree

iterator leaves[T](r: Node[T], depth:int, pfx=""): tuple[k:string, 
n:Node[T]] =
  type   #Nim iterators should 
grow
Which = enum st0, st1, st2, stR  #..recursion 
capability so
State = tuple[st: Which, k: string, n: Node[T]]  #..this headache can 
be as
  if r != nil:   #..easy as `print`.
var stack = newSeqOfCap[State](depth)
stack.add (st: st0, k: pfx, n: r)
while stack.len > 0:
  let state = stack[^1].addr
  if state.n == nil: break
  case state.st
  of st0:
state.st = st1
if state.n.kid[0] != nil:
  stack.add (st: st0, k: state.k, n: state.n.kid[0])
  of st1:
state.st = st2
if state.n.ch == NUL:
  yield (k: state.k, n: state.n)
elif state.n.kid[1] != nil:
  stack.add (st: st0, k: state.k & $state.n.ch, n: state.n.kid[1])
  of st2:
state.st = stR
if state.n.kid[2] != nil:
  stack.add (st: st0, k: state.k, n: state.n.kid[2])
  of stR: discard stack.pop


Run

The above is probably pretty close to what compilers generate for recursive 
function calls. Of course, as mentioned I think things like this are more 
elegant/easy to understand: 


proc print*[T](p: Node[T], depth=0) = #2,1,0 gives std emoji-orientation
  if p == nil: return #..i.e. ":-)" head-tilt not "(-:".
  print(p.kid[2], depth + 1)
  echo strutils.repeat("  ", depth), cast[int](p), " ch: ", p.ch.repr, " 
cnt: ", p.cnt
  print(p.kid[1], depth + 1)
  print(p.kid[0], depth + 1)


Run

For `cligen/trie.nim` since I was already using a super wasteful uncompressed 
trie, I just punted on all that and spent memory proportional to the answer, 
i.e.: 


proc collect*[T](n: Node[T], key: var string, d=0, pfx="", i=0): 
seq[tuple[k: string, n: Node[T]]] =
  if n == nil:
return
  if n.term:
result.add (k: (if i > 0: pfx[0..

Re: What’s your favorite programming language and why?

2019-12-18 Thread Stefan_Salewski
Funny question of a new forum user, isn't it?

So lets wait for nice new spam links:

[https://www.reddit.com/r/learnprogramming/comments/7zip4n/whats_your_favorite_programming_language_and_why](https://www.reddit.com/r/learnprogramming/comments/7zip4n/whats_your_favorite_programming_language_and_why)/


Re: Walking trees without recursive iterators

2019-12-18 Thread JohnAD
It is always possible to move a recursive algorithm to a non-recursive one; 
even avoiding psuedo-stacks or tail-recursion games.

It is, ironically, something I enjoy doing because it is quite the intellectual 
puzzle sometimes. The toughest one I did was with the Negamax (Minimax with 
restrictions) in a python library. (Sorry, I've not moved it to Nim yet.)

But, for context: writing a normal negamax algo in any language takes, perhaps, 
a few hours in any language. But, writing the non-recursive one, involved 
multiple convoluted arrays and more complex edge cases than I've ever 
encountered before. It took over a week of intense work.

SO,

Anything your head can do can be described in an algorithm with enough scrutiny.

(BTW, the non-recursive version of negamax is about 3 to 8 times faster. But it 
uses lots more memory.)


Re: assign an object variant kind for unsafe memory block

2019-12-18 Thread mrgaturus
thanks, i used -d:nimOldCaseObjects because the compiler source uses it on 
nim.cfg. i use `alloc0` for arbitrary blocks size, ex: `alloc0(sizeof(AHeader) 
+ blocksize)`


Re: Walking trees without recursive iterators

2019-12-18 Thread e
Does this test


if handle.par.len - 1 < handle.kidIx: false #kid@kidIx was deld post yield


Run

mean that deletion is only supported for the last kid (or all kid s)? E.g., if 
I don't delete kid 5, but then delete kid 4, isn't len still 4, so the test 
fails and we process kid 4's kids?


Re: What’s your favorite programming language and why?

2019-12-18 Thread JPLRouge
Bonjour :

42 year pratique : IBM 34/36/38/AS400 -->RPG2/3/4 project using the “AXIAL” 
method

  * object oriented "RPG-ILE" "C-ILE" language
  * C++



traditional project management create L4G type engine

sur pc : 1980: pascal / C 1990 ... 2019: C++ PHP2/3 Javascript creation driver 
for picking creation concept soft for press

2019/10: NIM : very interesting approach, after trying "RUST", I succumbed to 
the charm of Nim-lang

I work on a project with "NIM" with the option of using the "AXIAL" method 
reproduce the AS400 BD / INTERACTIVE / EDITION type access methods oriented 
RPG4(ibm) 


Re: nim android tutorial

2019-12-18 Thread cblake
Also, it's not an "app", but it bears re-iterating that Nim on Termux works 
just like Nim on a worstation/laptop/other posix-y environment. See, e.g, 
[https://forum.nim-lang.org/t/2891](https://forum.nim-lang.org/t/2891). I have 
a couple dozen Unix commands that compile and run just fine in both 
environments.


Re: Arrays and Sequences in nim

2019-12-18 Thread cblake
As a point of clarification, depending a bit on OS and sysadmin settings, one 
can usually increase stack limits with `ulimit -s unlimited` builtin for most 
shells, maybe `/etc/limits` or `/etc/security/limits.conf` on Linux or even 
_adjustable in-program_ by `setrlimit` (if not blocked by admin settings). 
(Nim's stdlib could use an `RLIMIT_STACK` constant to ease that last one.)

The default limits are usually much less than say system memory divided by 
number of expected threads. It would be very rare that all threads used their 
limit anyway. When the limit is exceeded your thread/process just crashes, much 
as if you set the limit to be unlimited and used all system memory.

The existence of low stack limit defaults historically mostly comes from 
systems with "spinning rust" rather than than NVMe backing store for swap. On 
such systems, an unbounded recursion could bring the machine to a crawl for all 
users. So, the limit was a safety feature. These days, no swap at all is a real 
possibility. Even when swapping is enabled, the limit is more about not having 
some unbounded recursion flush filesystem caches forcing re-reads. Also, kernel 
code often has small stack limits for related but distinct reasons 
(non-swappability of kernel stack/page fault handlers/etc.). Kernel developers 
tend to set default limits based on what they think is "good for you" based on 
their own very stack-conservative styles.

Anyway, the short of it is that if stack is how you would prefer to manage your 
memory (for whatever reasons) there isn't anything intrinsically wrong with 
that related to "size". There's just a little deployment complexity, like maybe 
erroring out if admins have blocked stack limit increasing and your `setrlimit` 
fails which is atypical in my experience. (This is all Unix advice. I have 
little to no experience for how this plays out on Windows, but some more 
informed person can perhaps chime in.)


Re: What’s your favorite programming language and why?

2019-12-18 Thread drkameleon
> Interesting. Why do you hate Python?

Well, it's a bit controversial I know. I have a friend who swears by it. 
However, whenever I _had_ to write sth in Python, I end up struggling either 
with the different versions, virtual environments (or 
I-don't-know-how-it's-called), missing modules that cannot get installed 
no-matter-what (or basically do not have the patience to learn how to) and last 
but not least... indentation issues (yes, I know... we're in a Nim forum, but 
for some reason I've never been a huge fan of the... "off-side" rule).

Now, if it was as performant for systems' programming as Nim, I might have 
given it a second chance... lol


Re: Walking trees without recursive iterators

2019-12-18 Thread cblake
In the interests of a more self-contained thread and to perhaps more easily see 
what it's doing, here is a more brief version of @sschwarzer's algorithm: 


import xmltree

type Handle* = tuple[kidIx: int; par, kid: XmlNode]   #Ix of kid in parent

iterator handlesHiToLo*(node: XmlNode): Handle =
  ## Recursively yield ``Handle`` objects for direct kids of 
``node``
  ## from high to low index order (on same level). { This order simplifies
  ## removing kids in-place without affecting later yielded kid indices. }
  ## The root node is included in yielded ``Handle``s with a ``nil`` parent.
  
  template recordYield(par: XmlNode, kidIx: int, kid: XmlNode=nil) =
handle = (kidIx, par, (if kid.isNil: par[kidIx] else: kid))
yield handle
  
  proc high(node: XmlNode): int = node.len - 1
  
  var done = false#flag to stop outer loop from inner
  var stack = newSeq[Handle]()
  var handle: Handle  #Last node yielded
  
  recordYield nil.XmlNode, 0, node#Always yield the root first
  if node.len == 0: done = true   #Nothing left to do
  else: recordYield node, node.high   #Start from high node of root & 
proceed
  while not done:
let kidHasKids =
  if handle.par.len - 1 < handle.kidIx: false #kid@kidIx was deld post 
yield
  else: handle.kid.len > 0
if kidHasKids:#Descend tree, build stack, yield last 
grandkid
  stack.add handle
  recordYield handle.kid, handle.kid.high
  continue
while true:   #Yield next (lower index) kid | maybe 
pop,find new
  if handle.kidIx >= 1:
recordYield handle.par, handle.kidIx - 1
break
  if stack.len > 0:
handle = stack.pop()
  else:   #No more nodes to try on the stack. Done.
done = true
break


Run

If you want some other visitation order such as low-to-high then you have to 
adjust things a bit. For in-order/work in the middle you might need to adjust 
it a lot.

I actually kind of doubt it can be simplified if you want to preserve the 
deleteability of nodes pointed to by yielded handles.

In these sorts of situations, recursive code is often drastically more clear. A 
good programming language should facilitate clear code. Therefore Nim iterators 
should grow recursion capability someday. But I'm not signing up to implement 
it, and I wouldn't assert it's a high priority.


Re: What’s your favorite programming language and why?

2019-12-18 Thread adrianv
I like - in the order of appearance in my life:

  * pascal for showing me that Apple Basic was crap
  * forth for showing me how powerful it can be to do things in the reverse 
order
  * delphi for simplifying GUI development in 1995
  * haxe for giving me the ability to program JavaScript or php (and others) 
without touching them in a type safe manner
  * nim for its power and not over OOPing everything



I don't like:

  * C++ for wasting my time
  * php because its ugly
  * JavaScript just because




Re: What’s your favorite programming language and why?

2019-12-18 Thread juancarlospaco
HLA: High Level Assembly, used to be like a Nim that compiled to Assembly, 
32Bit only, dead.

Scala-Native: Dont need Java, has Java as part of its std lib. 


Re: how to create a generic type with constraints?

2019-12-18 Thread mashingan
Checking with 
[compiles](https://nim-lang.github.io/Nim/system.html#compiles%2Cuntyped) 
should enough


when compiles(hash(a)): # a is the T object
  doWith(a)
else:
  {.error: "need hash implementation of " & T.type.}


Run

It's checked during compile-time.


Re: how to create a generic type with constraints?

2019-12-18 Thread geotre
These are great examples of concepts, I had no idea that last one would even be 
possible


Re: What’s your favorite programming language and why?

2019-12-18 Thread mashingan
Same here, love Erlang's philosophy too :D


Re: What’s your favorite programming language and why?

2019-12-18 Thread foldl
Interesting. Why do you hate Python?

I like:

  * Erlang for its philosophy
  * Mathematica for astonishing me
  * C# for its creator
  * Nim for its clarity and power
  * Pascal for bringing me to this wonderful journey, too



I hate:

  * Java for over-designed design patterns
  * Rust for failing to compile my hello world




Re: What’s your favorite programming language and why?

2019-12-18 Thread drkameleon
Having been programming fo over 25 years, I most definitely couldn't say just 
one. But I could definitely say a few for sure.

  *  _Ruby_ : because it's the one I'm most familiar with, it's dynamic, 
flexible and I "get the work done" fast
  * _Haskell_ : because of it's power, elegance and logic - although I'm by no 
means good at it
  * _Lisp_ : for inside logic, S-expressions, etc
  * _Rebol_ : for the same reason as above, only more elegant
  * _Arturo_ : (shameless plug ahead) because of all the above and because it's 
my own brain-child
  * _Nim_ : for its clean code and great performance
  * _Pascal_ : for sentimental reasons, since it's the one that got me started 
in this wonderful journey, when I was still a kid




Re: What’s your favorite programming language and why?

2019-12-18 Thread mratsim
I doubt you will get unbiaised answers on the Nim forum.

What's yours and why?


Re: how to create a generic type with constraints?

2019-12-18 Thread marks
Thanks. I think I'll do without concepts for now.


What’s your favorite programming language and why?

2019-12-18 Thread tonyruffalo
Let’s discuss

I would love to hear people’s stories and experiences


Re: Introducing Synthesis: a Finite State Machine generator

2019-12-18 Thread mratsim
Something like `Graphviz` or `GraphML` to display the state machine with its 
transition visually.


Re: Arrays and Sequences in nim

2019-12-18 Thread mratsim
A couple of notes:

  * Your stack size of 10_000_000 is very big. That would only work with global 
arrays as those are statically assigned a size at program start. However if 
used within a function you will most certainly stack overflow. For example a 
stack of int would take 80_000_000 bytes = 80MB but max stack size is about 8MB 
on most machines. If this is used within a function you will have to allcoate 
it on the heap with a ref array or just use a seq.
  * In terms of speed, if the address of the seq and the address of the arrays 
are hot in cache, there is no difference. Data structures on the stack are 
always hot in cache within a function.
  * The `base_addr_offset + index * size` computation to address each elements 
of a seq/array doesn't matter in general for 2 reasons:

* The size of an object is power of 2 (due to padding and alignment) and 
x86 can do offset + index * pow2 addressing in a single instruction without a 
multiplication via something called SIB addressing (Scaled Index Byte) for 
types of size 1, 2, 4 or 8: 
[https://wiki.osdev.org/X86-64_Instruction_Encoding#SIB](https://wiki.osdev.org/X86-64_Instruction_Encoding#SIB)
* It is very likely that the bottleneck is either memory or branch 
predictions and that your CPU has a lot of free time to do those computations 
in between waiting for data from the L1/L2 cache.




Re: Any way to see the generated assembly?

2019-12-18 Thread drkameleon
Great, thanks! :)


Re: how to create a generic type with constraints?

2019-12-18 Thread mratsim
If I didn't mess up my concept syntax 


type Diffable = concept x, y
  `==`(x, y) is bool
  hash(x) is Hash


Run

See: 
[https://nim-lang.org/docs/manual_experimental.html#concepts](https://nim-lang.org/docs/manual_experimental.html#concepts)

And actual use cases:

  * Enqueueable concept: 
[https://github.com/mratsim/weave/blob/a8f42d302e3d68f397374e9b14e964f647cb9afa/unused/channels/channels_mpsc_unbounded.nim#L8](https://github.com/mratsim/weave/blob/a8f42d302e3d68f397374e9b14e964f647cb9afa/unused/channels/channels_mpsc_unbounded.nim#L8)




type
  Enqueueable = concept x, type T
x is ptr
x.next is Atomic[pointer]


Run

  * IntrusiveStackable concept: 
[https://github.com/mratsim/weave/blob/ed177fffaea6dbd6b7ddb648fc6e9cb302cae2ff/weave/memory/lookaside_lists.nim#L11-L14](https://github.com/mratsim/weave/blob/ed177fffaea6dbd6b7ddb648fc6e9cb302cae2ff/weave/memory/lookaside_lists.nim#L11-L14)




type
  IntrusiveStackable* = concept x, type T
x is ptr
x.next is T


Run

  * StealableTask concept: 
[https://github.com/mratsim/weave/blob/78c9033c1bbee5a8efde2d623d9e7cc8b9605f77/weave/datatypes/prell_deques.nim#L11](https://github.com/mratsim/weave/blob/78c9033c1bbee5a8efde2d623d9e7cc8b9605f77/weave/datatypes/prell_deques.nim#L11)




type
  StealableTask* = concept task, var mutTask, type T
## task is a ptr object and has a next/prev field
## for intrusive doubly-linked list based deque
task is ptr
task.prev is T
task.next is T
# A task has a parent field
task.parent is T
# task has a "fn" field with the proc to run
task.fn is proc (param: pointer) {.nimcall.}


Run

  * NeuralNetwork Layer concept: 
[https://github.com/mratsim/Arraymancer/blob/f06c43db379d1ef0160315162a45a8ab5bdb2b0d/src/nn_dsl/dsl_types.nim#L63-L68](https://github.com/mratsim/Arraymancer/blob/f06c43db379d1ef0160315162a45a8ab5bdb2b0d/src/nn_dsl/dsl_types.nim#L63-L68)




type
  TrainableLayer*[TT] = concept layer
block:
  var trainable: false
  for field in fields(layer):
trainable = trainable or (field is Variable[TT])
  trainable


Run

The last one is a bit hard, basically a concept must satisfy several 
properties, and that is checked by each statement returning `true`, so what I 
do there is creating a temporary bool called trainable in the concept and I 
check that recursively at least one field in the type or its subtypes is of 
`Variable[TT]` which would be something trainable in my framework. If there is 
at least one such field, it returns true and it's considered a 
`TrainableLayer[TT]`.


Re: Any way to see the generated assembly?

2019-12-18 Thread mratsim
See the flags I mentioned here: 
[https://github.com/nim-lang/Nim/issues/12578](https://github.com/nim-lang/Nim/issues/12578)

There is a new --asm flag in Nim devel but it generates a lot of fluff.


Re: Walking trees without recursive iterators

2019-12-18 Thread sschwarzer
I've written an iterator over an `XMLNode`:

[https://hg.sr.ht/~sschwarzer/vppdiff/browse/default/src/vppdiff/cleanxmi.nim#L46](https://hg.sr.ht/~sschwarzer/vppdiff/browse/default/src/vppdiff/cleanxmi.nim#L46)

Internally the iterator uses a stack.

Iterator features:

  * You can modify the tree while iterating over it. For example, if you delete 
a child node, the iterator doesn't yield _its_ child nodes.
  * For each iteration, the iterator gives you parent node, child index and 
child node in a `NodeDescription` object, so you can delete the child node with 
`parent_node.delete(child_index)`.
  * The iterator goes from higher to lower child indices, so deleting child 
nodes doesn't shift the indices for the remaining child nodes in subsequent 
iterations.



I suspect the implementation is more complicated than it has to be, but this 
code is what I've been able to come up with. ;-)


how to create a generic type with constraints?

2019-12-18 Thread marks
I'm trying to port Python's difflib's sequence matcher to nim. I want to be 
able to compare any two sequences of the same types, not just strings.

I have this type: 


type
  Diff[T] = object
a: seq[T]
b: seq[T]
b2j: Table[T, seq[int]]


Run

How can I say that type `T` must support `==` and `hash()`?


Any way to see the generated assembly?

2019-12-18 Thread drkameleon
I'm on a Mac and using clang.

I know where the generated C files are, but when trying to compile them, I see 
all sorts of missing header files, etc. I can sure make it work, but is there 
any already-available way to see just the generated assembly without messing 
around?


Re: Arrays and Sequences in nim

2019-12-18 Thread Stefan_Salewski
> This is a very interesting point.

And to make it more precise: When we access an arbitrary element of a array/seq 
base address + index * element_size is calculated to determine its memory 
address and access it. If multiple elements are accessed one after the other, 
then a compiler is generally smart enough to see that only adding element_size 
to current address is needed to access next element. Long time ago, when 
compilers were not that smart, constructs like my_element_ptr++ was used to 
access next element. But today using a plain index generally generates the same 
optimized code when possible. 


Re: Arrays and Sequences in nim

2019-12-18 Thread drkameleon
> If array index is a constant, then offset is constant too. If array index is 
> a variable, than offset is product of element_size and offset. So there is a 
> runtime mul in later case.

This is a very interesting point.

Given that what I'm currently doing is building a stack machine bytecode 
interpreter (to replace my AST-walking interpreter) - and already seeing some 
serious perfomance upgrade, I'm trying to use every trick available, so these 
subtle details do matter.

Currently, my simple "stack" is pretty much like that:


#[##
Constants
  ==]#

const
MAX_STACK_SIZE = 10_000_000

#[##
Types
  ==]#

type
Stack[T]= array[MAX_STACK_SIZE,T]

Value   = uint64

#[##
Global variables
  ==]#

var
MainStack*  : Stack[Value]   # my main stack
MSP*: int# pointer to the last element

#[##
Implementation
  ==]#

template push*(v: Value) = inc(MSP); MainStack[MSP] = v
template pop*(): Value   = dec(MSP); MainStack[MSP+1]

template popN*(x: int)   = dec(MSP,x)

template top*(x:int=0): Value= MainStack[MSP-x]


Run

so... normally an **ADD** instruction, in my {.computedGoto.} interpreter loop, 
would be something like that:


case OpCode
# other cases
of ADD_OP: push(pop()+pop()); inc(ip)
# inc(MSP); MainStack[MSP] = ((dec(MSP); MainStack[MSP+1]) + (dec(MSP); 
MainStack[MSP+1]))
# ...


Run

which I'm optimizing further (I think... lol) by doing it like: 


case OpCode
# other cases
of ADD_OP: top(1) = top(0)+top(1); dec(MSP); inc(ip)
# MainStack[MSP-1] = MainStack[MSP]+MainStack[MSP-1]; dec(MSP)
# ...


Run

So... lots of different things going on...

Any ideas to make it better (and more performant) are more than welcome! :)


Re: Introducing Synthesis: a Finite State Machine generator

2019-12-18 Thread Araq
> It generates compact code: the code generator is based on the undocumented 
> goto pragma.

Maybe it's time to document it then... :-)


Re: Arrays and Sequences in nim

2019-12-18 Thread Stefan_Salewski
Maybe one additional note:

When we access elements of an array, that generally occurs with an offset to 
stackpointer. Stackpointer is generally fixed while we are inside a proc, and 
stackpointer is generally located in a register, so to access an array element 
a offset plus stackpointer is used to locacte the array element. If array index 
is a constant, then offset is constant too. If array index is a variable, than 
offset is product of element_size and offset. So there is a runtime mul in 
later case.

To access an element of a seq, there is some indirection: First the base 
address of the pointer to payload is moved into a CPU register, and an offset = 
(elementsize * index) is added to locate element. When we access many elements 
of a seq, then only one time its payload address needs to be moved into a CPU 
register, so accessing many elements is not really slower for seq than it is 
for array. 


Re: Arrays and Sequences in nim

2019-12-18 Thread drkameleon
Thanks a lot for the explanation!

This is pretty much what I expected - but no harm getting a second opinion to 
make sure you got things right, nope? :)

Basically, I have experimented with pretty much everything A LOT **and** 
benchmarked it **and** checked the produced C code, but wanted to make sure... 
And from what I've observed and from what you say, we're definitely on the same 
page.

My latest experiments point to the same conclusion as well:


var arr: array[10,byte]

echo cast[uint64](addr arr)
echo cast[uint64](addr arr[0])
echo cast[uint64](addr arr[1])
echo cast[uint64](addr arr[2])


Run

The first two - quite obviously - point at the beginning of the array. And the 
next ones point at the consecutive "cells" of memory, one _byte_ apart...

In any case, again: thanks ;-)


Re: Arrays and Sequences in nim

2019-12-18 Thread Stefan_Salewski
I think that question has been answered many times already, and I am nearly 
sure you know it already. At least you are no newbie, I have seen you name in 
this forum for at least a few months already :-)

Nim array is basically a C array located on the stack, so just a fixed block of 
memory. As it is located on the stack there is no alloc/dealloc needed, 
allocation is just increasing the stack pointer. Dont't ask me how returning a 
array from a proc works exactly, but I assume it works also without 
alloc/dealloc.

seq and string is basically an object, at least one length field and a pointer 
to payload, that is the real data content. Content is dynamically allocated and 
deallocated. When data elements are added, data buffer may get exhausted, then 
a new payload buffer is allocated and data is copied there. There may be 
exceptions, as when area after buffer is still unused, OS may allow increasing 
a buffer already in use, that operation may be called realloc() or something 
like that. seq and string works very similar to C++ std::vector. Details my 
vary for Nim V2, newruntime, arc memory management and all that what may come.

Note, C may allow dynamically sized arrays living on stack. That can work for 
special cases, as stack pointer can be increased dynamically at runtime. There 
exists a forum post to this behaviour.

And finally there is openArray, basically a container for passing array or seq 
to procs, so I assume it is a length field and a pointer to payload.