Re: Is it possible for a macro to know the context it is used?

2020-05-18 Thread jcosborn
Ah, you probably want `declared` instead of `declaredInScope`. The latter only 
works for the immediately enclosing scope and not the ones above it. The 
documentation may not be very clear on that 
[https://nim-lang.org/docs/system.html#declared%2Cuntyped](https://nim-lang.org/docs/system.html#declared%2Cuntyped).
 


import macros

template foo(body: untyped) =
  block:
let inFoo {. inject, used .} = true
body

template bar(body: untyped) =
  block:
let inBar {. inject, used .} = true
body

proc callApiFromFoo =
  echo "Calling API with foo scope"

proc callApiFromBar =
  echo "Calling API with bar scope"

template callApi =
  when declared(inFoo):
callApiFromFoo()
  elif declared(inBar):
callApiFromBar()
  else:
echo "You can call API only in foo or bar scopes!"

proc foobar =
  foo:
block:
  callApi()
  
  bar:
block:
  callApi()

foobar()


Run


Re: Is it possible for a macro to know the context it is used?

2020-05-18 Thread spip
Could you explain how/why it works?

I have reproduced that pattern in my project and it works **sometimes but not 
always** , and I don't understand why.

When it does not work, I have changed the `callApi` template to be like: 


template callApi =
  when declaredInScope(inFoo):
callApiFromFoo()
  elif declaredInScope(inBar):
callApiFromBar()
  else:
echo "inFoo scope? = ", declaredInScope(inFoo)
echo "inBar scope? = ", decalredInScope(inBar)
error("You can call API only in foo or bar scopes!")


Run

And in the `foobar` proc (a macro in my case), I dump the whole AST tree. I can 
see that `inFoo` or `inBar` are correctly defined and deeper in the tree I find


  LetSection
IdentDefs
  PragmaExpr
Ident "inFoo"
Pragma
  Ident "inject"
  Ident "used"
  Sym "Bool"
  Call
   ...
  Command
Ident "echo"
Call
  Ident "callApi"


Run

(in that specific case, `callApi` returns a `string`)

But the call `callApi` goes in the `else:` branch and I see 


echo ["inFoo scope? = ", "false"]
echo ["inBar scope? = ", "false"]
error("You can call API only in foo or bar scopes!",
  nil)


Run

The case where it fails is more complex than this example. It is like 
`declaredInScope` does not return the correct result in that particular 
situation. I've tried to look at the code for `declaredInScope` but that's a 
[magic 
function](https://github.com/nim-lang/Nim/blob/version-1-2/lib/system.nim#L163) 
and I can't find it to understand how it works.

In case it could be useful to find the source of the problem, compilation fails 
with the error message (which is true because `callApi` expects to return a 
`string` but that's the error case...) 


Error: expression has no type:
echo ["inFoo scope? = ", "false"]
echo ["inBar scope? = ", "false"]
error("You can call API only in foo or bar scopes!",
  nil)


Run


Re: Is it possible for a macro to know the context it is used?

2020-05-17 Thread jcosborn
You could do it by wrapping in a template 


import macros

template foo(body: untyped) =
  block:
let inFoo {. inject, used .} = true
body

template bar(body: untyped) =
  block:
let inBar {. inject, used .} = true
body

proc callApiFromFoo =
  echo "Calling API with foo scope"

proc callApiFromBar =
  echo "Calling API with bar scope"

template callApi =
  when declaredInScope(inFoo):
callApiFromFoo()
  elif declaredInScope(inBar):
callApiFromBar()
  else:
echo "You can call API only in foo or bar scopes!"

proc foobar =
  foo:
callApi()
  
  bar:
callApi()

foobar()


Run


Re: Is it possible for a macro to know the context it is used?

2020-05-17 Thread spip
In other words, is it a part of the job that I can delegate to the Nim compiler 
semantic parsing phase or it it something I must do before it, when I'm 
managing the DSL syntax?


Re: Is it possible for a macro to know the context it is used?

2020-05-17 Thread spip
I reopen this thread as I'm facing a similar problem, but now when calling an 
API.

Is it possible to write a proc whose behaviour is based on existence or not of 
macro injected variables? I've tried to reproduce a sample case below:


import macros

template foo(body: untyped) =
  block:
let inFoo {. inject, used .} = true
body

template bar(body: untyped) =
  block:
let inBar {. inject, used .} = true
body


proc callApi =
  if declaredInScope(inFoo):
echo "Calling API with foo scope"
  elif declaredInScope(inBar):
echo "Calling API with bar scope"
  else:
echo "You can call API only in foo or bar scopes!"


proc foobar =
  foo:
callApi()
  
  bar:
callApi()

foobar()


Run

This code **does not give the expected result!**

What I'm trying to do and that does not work: the `callApi` proc takes no 
parameters and depend on the scope it is used to call different API entry 
points. Its behaviour is really given in the scope it is used. In order to 
determine in which scope it is used, I've tried to inject 2 different variables 
`inFoo` and `inBar` and base `callApi` behaviour on the presence or absence of 
these variables in the scope.

Having changed the way my DSL works, I'm now able to know in which 
scope/context the AST is parsed. But in that case, `callApi` is a Nim function 
that can be called by the user and I don't want for these types of functions to 
have a complex syntax: the user knows if she is using it in the `for` or `bar` 
contexts and that's the reason it doesn't have arguments in my example.

Behind the scene, I have two functions `callApiFromFoo` and `calApiFromBar` 
with all the parameters required. I want to be able to find which function to 
call...

Is the only way to get the expected result to parse the whole AST tree and when 
finding a `callApi` call NimNode, replace it with `callApiFromFoo` (resp. 
`callApiFromBar`) when in the `foo` (resp. `bar`) scope?

Or is there another way to solve this problem?


Re: Is it possible for a macro to know the context it is used?

2020-05-13 Thread Araq
> Instead of having multiple small macros that don't play well together and 
> have only a local context, I'll apply a visitor-like pattern and I can 
> control the scopes in the DSL.

Yes! Now you're cooking.


Re: Is it possible for a macro to know the context it is used?

2020-05-13 Thread spip
Night has been enlightening. I understand my error. Instead of having multiple 
macros `algo1`, `evaluate`, etc. that are called when Nim compiler evaluates 
the syntax tree from the `dsl```call, I must see ``dsl` as a compiler itself. 
Now, I have only one macro, `dsl`, that is used to convert its argument to an 
AST, and then this AST is parsed/translated by procs in a new AST that will be 
used by the Nim compiler.

Instead of having multiple small macros that don't play well together and have 
only a local context, I'll apply a visitor-like pattern and I can control the 
scopes in the DSL.

Thanks @dawkot for forcing me to think out of the box with your example.


Re: Is it possible for a macro to know the context it is used?

2020-05-13 Thread dawkot
If there's a pattern of doing init(...), evaluate: ..., let ... = getValue(), 
then you can convert it to something like this: 


dsl:
  algo1 as x:
echo x
algo2(x) as y:
  echo y


Run


Re: Is it possible for a macro to know the context it is used?

2020-05-12 Thread spip
Well, the DSL is more a language than a fixed structure. I gave a small sample 
code to feel it but you could have code like: 


dsl:
  algo1:
evaluate:
  # Do something with algo1 result
  let x = getValue()
  algo2:
# Using x to calculate algo2
init(x)
evaluate:
  # Getting a new value
  let y = getValue()
etc.


Run

That's the reason why `dsl`, `algo1` and `algo2`, `evaluate` are macros in that 
example that can be combined by the user. `dsl` is used by the user to start 
using the DSL syntax. `algo1` and `algo2` are two keywords of the DSL to do 
some operations, and `evaluate` is another keyword to get access to result from 
these operations.

Like I said, eventually the solution would be to change the DSL syntax, either 
by using dedicated `evaluate1` and `evaluate2`, but in the real DSL I could 
have more that 2 `algoN` and having a single keyword for a common action is 
more orthogonal. Or do you have a better idea?


Re: Is it possible for a macro to know the context it is used?

2020-05-12 Thread dawkot
This is how I would do it 


import macros

macro dsl(nodes) =
  result = newStmtList()
  for n in nodes:
var value: NimNode
if eqIdent(n[0], "algo1"): value = newLit"Foo"
elif eqIdent(n[0], "algo2"): value = newLit(123)
else: error "Unexpected ident: ", n[0]
for kid in n[1]:
  if eqIdent(kid[0], "evaluate"):
let body = kid[1]
result.add quote do:
  template value: untyped = `value`
  `body`
  else:
error "Unexpected ident: ", kid[0]

dsl:
  algo1:
evaluate:
  echo "[algo1] Evaluation is " & $value
  algo2:
evaluate:
  echo "[algo2] Evaluation is " & $value


Run


Is it possible for a macro to know the context it is used?

2020-05-12 Thread spip
For instance, I have a small dsl like: 


dsl:
  algo1:
evaluate:
  echo "Evaluation is " & $value
  algo2:
evaluate:
  echo "Evaluation is " & $value


Run

The role of `evaluate` is to retrieve the result of calculation using `algo1` 
or `algo2` that use different data structures in an external API. So when 
`evaluate` is called in the context of `algo1`, it must call a different API 
than when used in the context of `algo2`.

The simplest solution would be to use different names for `evaluate` in context 
1 vs 2, like `evaluate1` and `evaluate2`.

Another solution, in `evaluate`, would be being able to detect when walking up 
the AST if it contains NimNode calls with "algo1" or "algo2". But I don't think 
that you can walk up the AST to the root like you can do down to the children 
with 
[findChild](https://nim-lang.org/docs/macros.html#findChild.t%2CNimNode%2Cuntyped)
 for instance.

Another idea is for `algo1` and `algo2` to set the algorithm used in a variable 
and let `evaluate` retrieve the value of that variable before calling the API. 
But if the macro `evaluate` is executed in an `untyped` context from `algo1` / 
`algo2`, it can't access that variable content because that context hasn't been 
semantically checked yet, if I understand correctly.

What would be an approach to solve that problem? Please note that I've 
simplified my problem and that in the real DSL, there could be multiple layers 
of block calls between `algoX` and `evaluate`.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread cblake
Someday destructors may be defined/automatically called, but today there will 
be no clean-up without the `close` call. You may not need to/want to clean-up 
anyway.

need to: `memfiles.open()` creates a memory mapping, but does not (by default) 
keep the file descriptor open. The only thing the `mf.close` above does is call 
`munmap`. Memory maps are a less scarce resource than file handles due more to 
default OS limits than anything else. Being much less scarce, it's not quite as 
bad to leak it.

want to: You might even want to leak it on purpose if you wanted to keep the 
string data alive beyond the lifetime of the procedure invocation. E.g., you 
may want to return an `MemSlice` or a `Table` with them as keys or values. They 
are just pointers to that memory mapped region (hence zero copy) which means if 
you `mf.close/munmap` the pointers become invalid.

Of course, if you are leaking millions of memory mappings then even small leaks 
can grow to be burdensome on the OS -- if you don't need continued access to 
the data. So, as with all resource management there is a balance of concerns 
and trade offs.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread adnan
Very sorry to be annoying but with --gc:arc, is it necessary to close the 
memfile?


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread cblake
Well, the data "on disk" is not NUL-terminated. So, though the type I am using 
is called "cstring" the string data is not terminated. If anything, the data is 
more "newline terminated" in your file format. Those newlines are mapped out by 
the `memSlices` iterator, though with the result stored in `.size`. So, I just 
use that to bound the loop.

I used that type because Nim defines convenient `[]` style access to the bytes 
of a `cstring` giving back `char` s. It isn't strictly necessary, but that was 
my reason. (You would have to do your own pointer arithmetic and dereferencing 
otherwise).


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread adnan
Just a small question regarding your parseUint, you are taking an argument 
called size. If I convert something to a cstring, wouldn't I get a null 
terminated string? In which case I can just check if the char is 0 or not to 
end the loop.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread cblake
One vexing thing about modern CPUs is that a single CPU core cannot saturate 
RAM bandwidth. So, while throughput in L1 can be 100..200 GB/sec, and RAM 
bandwidth might be 50..150 GB/s, the amount just one L1 cache system can read 
from L2/L3/DIMMs might be only 5-30 GB/sec. This puts (often much simpler) 
single-threaded code that could otherwise saturate RAM throughput (thereby 
running as fast as possible anyway) at a major throughput disadvantage. But I 
totally agree with @mratsim here that staying with ST-code is the best idea.

The cynic inside me guesses the throughput disparity incentivizes people to 
write more parallel code, thusly selling more CPUs. So, these days CPU 
manufacturers are sadly incentivized to complicate lives of programmers. At the 
dawn of the industry, it was the other way around. Maybe there is some less 
cynical "scaling" problem, but usually with throughput/bandwidth you can just 
add more lanes of traffic.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread mratsim
Note that with a shared table, accesses will need to be serialized to ensure 
soundness and data consistency:

  * This means that threads will compete for cache accesses and might lead to 
cache thrashing/cache ping-pong/false sharing/cache invalidation. If your task 
per thread is short (less than micro-second ~ 1 cycles) and your table is 
small, you will likely experience a huge slowdown anywhere from 2x to 10x as 
threads compete for cache.
  * Nim shared tables are really really bad and should be removed from the 
standard library. It's only useful for proof-of-concepts but underneath it's 
just a shared heap allocated table + lock. Unfortunately writing fast and 
correct concurrent data structures is an extremely **hard** problem.
  * processing strings in parallel brings memory-management woes as strings are 
heap allocated and reclaiming memory that was allocated from another thread is 
about 5x slower at best than reclaiming memory from your own thread.
  * Furthermore if all the created strings ends up owned by the shared table 
thread you are in a producer/consumer scenario with many threads that depletes 
their extra memory cache and 1 thread that ends up hoarding lots of extra 
memory when it collect the strings, so both of their cache ends up useless. 
Unfortunately few memory allocators deal with that effectively (Microsoft's 
Mimalloc and Snmalloc), and it's the worst case behaviour for the default 
allocators in Linux, MacOS and Windows.



Lastly this part is suspect in terms of extra allocation 
`paramStr(1).open().readAll().splitLines().ytz()` as mentioned by @leorize

So I suggest you use @cblake code single-threaded.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread cblake
Oh, and if you did want to use a zero copy IO interface like `memfiles` on 
this, you can and indeed it is over 3X faster, but you have to write your own 
integer parser because `parseUint` and all its analogues take a Nim `string` 
not `MemSlice`. You can use the dollar operator `$` to convert, but that is no 
faster than just using `lines` in the first place. Parsing an integer in ASCII 
is actually pretty easy, though. E.g., 


import tables, os, memfiles

proc parseUInt(data: cstring, size: int): uint {.inline.} =
  let zero = ord('0')
  let nine = ord('9')
  for i in 0 ..< size:
let code = ord(data[i])
if code >= zero and code <= nine:
  result *= 10
  result += uint(code - zero)
else:
  return 0  #non-digit; parse error

proc ytz(path: string): uint =
var
  table = initTable[uint, uint]()
  mf = memfiles.open(path)
if mf.mem == nil:
quit("Cannot open " & path)
for s in memSlices(mf):
let n = parseUInt(cast[cstring](s.data), s.size)
if n == 0:
quit("Parse error: " & $s)
table.mgetOrPut(n, 0) += n
for key, val in table:
result = max(result, val)
mf.close

proc main() =
echo ytz(paramStr(1))

main()


Run

Not a big deal here, but if the file were really large that factor of 3 might 
be more appreciated.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread cblake
This topic can be confusing to beginners because the word "read" is overloaded. 
There is a "system call" named "read", but also many higher level APIs that are 
"buffered" which are also called "read", and people often refer to the general 
activity as just "reading". The buffering means those higher level APIs are 
doing "big reads" into a buffer and then copy small parts of that out for you 
for each line. If data is copied out shortly after it was read into that big 
buffer with a system-call read then the copy is cheap because it was from CPU 
caches (L1/L2/L3).

There are also "zero copy" APIs to do IO like "mmap" on Unix, or in the Nim 
world "memfiles". These let the OS itself do the "buffering" of what is in RAM 
vs "on disk" (or other persistent device like "flash memory" these days).

Your linked yahtzee file is only 900 KB with average line length of about 9 
bytes, but only 790 unique entries (so a small Table). With such a short line 
length you might profit from not creating new strings at all but re-using the 
same one over and over in the loop. That is because string creation and 
anything you might do with only 9 bytes take comparable time. The Nim stdlib 
also has a `split` iterator which lets you iterate over the split fields 
without creating a new `seq[string]`. Looking at your input file format there 
is no need to even `split` at all, though. So, there are simpler things than 
`memfiles` you can do to speed it up.

Also, because you only have 790 unique lines, it should be much faster to get 
the max value by looping over the `Table` after you are done creating it (both 
no 2nd lookup, and 790 <<< 100,000).

So, this is a faster version of your program: 


import tables, os, parseutils

proc ytz(path: string): uint =
var
table = initTable[uint, uint]()
n: uint
for numStr in lines(path):
if parseUInt(numStr, n) == 0:
quit("Parse error: " & numStr)
table.mgetOrPut(n, 0) += n # here
for key, val in table:
result = max(result, val)

proc main() =
echo ytz(paramStr(1))

main()


Run

Incidentally, when posting code to this forum, if you put `Nim` after the 
triple backquote it will be rendered with color syntax highlighting.


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread adnan
> [https://nim-lang.org/docs/sharedtables.html](https://nim-lang.org/docs/sharedtables.html)

Thank you, I never noticed it. I love Nim's stdlib!

> What would be faster is to read from the file line-by-line.

I always thought calling read() over and over again is fairly expensive. That 
said I wouldn't know better, I'm just a beginner programmer. In my test case, 
for this input: 
[https://gist.githubusercontent.com/cosmologicon/beadf49c9fe50a5c2a07ab8d68093bd0/raw/fb5af1a744faf79d64e2a3bb10973e642dc6f7b0/yahtzee-upper-1.txt](https://gist.githubusercontent.com/cosmologicon/beadf49c9fe50a5c2a07ab8d68093bd0/raw/fb5af1a744faf79d64e2a3bb10973e642dc6f7b0/yahtzee-upper-1.txt)
 which contains a billion lines of texts, reading the entire file seems 
marginally faster. 


Re: Is it possible to share a Hashmap between threads?

2020-03-13 Thread leorize
> Is there any way I can leverage multiple cores of the target system to 
> maximize efficiency?

Yes, but efficiency can't be guaranteed. The workload must be sufficiently 
large for the cores to most all of their time processing it, or else the 
bottleneck will fall into the creation and destruction of threads, which will 
make it slower than the single threaded version. See 
[https://forum.nim-lang.org/t/5909](https://forum.nim-lang.org/t/5909) for an 
example of inefficiency caused by threading.

But back to the main question:

> Is it possible to share a Hashmap between threads?

Yes, you can with this: 
[https://nim-lang.org/docs/sharedtables.html](https://nim-lang.org/docs/sharedtables.html),
 note that as the access to the table have to be placed behind a lock, this 
will actually decrease ability to do multiple core efficiently as they will 
spend most of the time waiting to have access to the table.

Your main bottleneck would be this snippet:


paramStr(1).open().readAll().splitLines().ytz()


Run

What would happen is that you `open` a file, then a cycle of string allocation 
& read syscalls until the file is read, then all of the resulting string is 
parsed for new lines, where each line will have their own strings allocated for 
the resulting seq then eventually passed to `ytz`. And all of that is really 
really slow.

What would be faster is to read from the file line-by-line. This can be done 
via the `lines` iterator, which will skip the huge overhead from reading then 
parse from the start to split by line, as the iterator returns each line as 
it's read from the disk.


Is it possible to share a Hashmap between threads?

2020-03-13 Thread adnan
In pursuit of optimizing the following code, I realized that if somehow the 
loop is paralleled (i.e. each thread operates on a certain chunk of the array), 
the code may execute faster:


import tables, os, parseutils, strutils

proc ytz(args: openArray[string]): uint =
var
table = initTable[uint, uint]()
n: uint
for numStr in args:
if parseUInt(numStr, n) == 0:
quit("Parse error: " & numStr)
table.mgetOrPut(n, 0) += n # here
if table[n] > result:  # here
result = table[n]  # and here

proc main() =
echo(paramStr(1).open().readAll().splitLines().ytz())

main()


Run

However I need to access the table (both mutably and immutably) in the places I 
pointed out. Is there any way I can leverage multiple cores of the target 
system to maximize efficiency? As far as I know Java has concurrent hashmap but 
I never used it myself.


is possible to defer a macro call?

2020-03-01 Thread mrgaturus
Hi everyone, i'm trying to create a enum type dinamically (not at runtime 
obviously) using macros. the problem is that the module where is called the 
macro for generate the enum is loaded before calling the macro for add enum 
fields and this doesn't add those fields, here is an example 


group Color
group Window
group Layer

generateGroupEnum(MyEnum) # Macro that i want defer
# Generates:
#  type MyEnum = enum
#grColor
#grWindow
#grLayer

group View
group Toolbar

# Expected Generate if it can defer:
#  type MyEnum = enum
#grColor
#grWindow
#grLayer
#grView -> Added
#grToolbar -> Added

when isMainModule:
  echo grLayer # 2
  echo grView # Error, not declared


Run


Re: Is this possible?

2020-02-27 Thread Divy
Ooh! That seems perfect...I'll test that out. Thanks.


Re: Is this possible?

2020-02-27 Thread enthus1ast
you can also consider creating shared object files and load them. Depending on 
your use case this might be "dynamic" enough?


Re: Is this possible?

2020-02-27 Thread Araq
See 
[https://github.com/nim-lang/Nim/blob/devel/tests/compilerapi/tcompilerapi.nim](https://github.com/nim-lang/Nim/blob/devel/tests/compilerapi/tcompilerapi.nim)
 and 
[https://github.com/nim-lang/Nim/tree/devel/tests/compilerapi](https://github.com/nim-lang/Nim/tree/devel/tests/compilerapi)
 for how to embed the compiler into your own projects.


Re: Is this possible?

2020-02-27 Thread Divy
Alrightyy! Thanks all for the answer.


Re: Is this possible?

2020-02-27 Thread Divy
@yglukhov, I am keen to understand the embedding of nim compiler. Could you 
give a example for the same?


Re: Is this possible?

2020-02-27 Thread SolitudeSF
juan's snippet still resolves import at compiletime. nim is not python.


Re: Is this possible?

2020-02-27 Thread Hlaaftana
That's just another method of doing it at compile time. Nim only supports 
compile time importing. Because it has to compile modules. Compiling is done 
once for the whole program.


Re: Is this possible?

2020-02-27 Thread Divy
Thanks that helped me understand it better :) What do you have to say about 
@juancarlospaco 's answer?


Re: Is this possible?

2020-02-27 Thread yglukhov
I think there's some misunderstanding here. The short answer to "is this 
possible?" is no, this is not possible. Since nim is a compiled language, all 
imported modules have to be compiled and embedded in the resulting binary. It 
is possible in dynamic languages that offer eval of some sort, but not in 
statically compiled languages.

Now in theory it is possible to make a lib that would allow eval and dynamic 
imports in some form, it would embed nim compiler in it, and maybe utilize hot 
code reloading, but i assure you, that's not something you want to consider at 
this point.


Re: Is this possible?

2020-02-27 Thread juancarlospaco

const some_module {.strdefine.} = "some_module"
template makeAnImport(module: static[string]): untyped = import module
makeAnImport(some_module)

Run

:)


Re: Is this possible?

2020-02-27 Thread xflywind
I have no idea.


Re: Is this possible?

2020-02-27 Thread Divy
Alright thanks anyway for the answer :) That atleast got me halfway...


Re: Is this possible?

2020-02-27 Thread Divy
How can I return the value that is returned in a proc inside the 
timeit_temp.nim?


Re: Is this possible?

2020-02-27 Thread xflywind
I mean if you want to import module dynaically, yon can write it directly into 
file or use when flag. for example, 


import streams, strformat

let
  module = readline(stdin)
  tempFile = getTempDir() & "timeit_temp.nim"
var temp = newFileStream(tempFile, fmWrite)

temp.writeLine(fmt"import {module}")
temp.write(othercode)


dicscard execCmdEx(fmt"nim c -r -f --d:{option} --verbosity=0 --hints=off 
--hint[source]=on " & tempFile)


Run

or


when defined(this):
  import this
elif defined(that):
  import that


Run


Re: Is this possible?

2020-02-27 Thread Stefan_Salewski
> please write Nim code like this

Maybe I missed a lot, but I have no idea what that part of your answer may mean 
and how it may help for the initial question.


Re: Is this possible?

2020-02-26 Thread Divy
Thanks! I'll try that


Re: Is this possible?

2020-02-26 Thread xflywind
IMO, Nim can't import module at run time. You must specify the name of module 
directly. 


import "jester"


Run

If you want to import module at run time, please write Nim code like this:). 


var temp = newFileStream(tempFile, fmWrite)
if not isNil(temp):
  temp.writeLine("import timeit")
  if def == "":
temp.writeLine("""var m = monit("test-whole")""")
temp.writeLine("m.start()")


Run


Is this possible?

2020-02-26 Thread Divy

var module = "jester"
import module


Run

If not, how do I implement something like this?


Re: Is it possible to see sql executed?

2020-02-15 Thread moigagoo
If you use Norm, you can use logging module to log all generated queries, just 
add import logging; addHandler newConsoleLogger()


Re: Is it possible to see sql executed?

2020-02-15 Thread dawkot
You should be able to just 


echo string(theQuery)


Run


Is it possible to see sql executed?

2020-02-15 Thread jjude
I'm using Jester to create a web-application. It connects to sqlite using 
db_sqlite. For debugging purposes is it possible to see sqls executed during 
development?


Re: Is it possible to browse the nimble.directory?

2019-12-19 Thread marks
Search is great if you know what you're looking for. But it is useless for 
getting an overview of what's available. And an overview of the third-party 
libraries is what I want when starting with a new language.


Re: Is it possible to browse the nimble.directory?

2019-12-13 Thread federico3
The current tags are far from descriptive, while categories organize packages 
only along one arbitrary dimension.

A much better taxonomy in used in Debian by Debtags: 
[https://salsa.debian.org/debtags-team/debtags-vocabulary/blob/master/debian-packages](https://salsa.debian.org/debtags-team/debtags-vocabulary/blob/master/debian-packages)
 because it implements 
[https://en.wikipedia.org/wiki/Faceted_classification](https://en.wikipedia.org/wiki/Faceted_classification)

For example, nmap is tagged: admin::monitoring, implemented-in::c, 
interface::commandline, network::scanner, role::program, scope::utility, 
use::scanning


Re: Is it possible to browse the nimble.directory?

2019-12-08 Thread spip
That's one of the many reasons why I listed all the packages available in 
Nimble this summer, and documented them in a [Google 
Sheet](https://docs.google.com/spreadsheets/d/1HWy2YumMMcgEDHk34ACauuWR5TYDJTRUVQ6B-LuRXCs/edit?usp=sharing)
 where you can use the **Categories** columns to regroup them.

I had suggested adding this information to Nimble and even proposed a [pull 
request](https://github.com/nim-lang/packages/pull/1165). Maintaining this 
information in a file, JSON or Google Sheet is not ideal though. A central 
repository like [https://nimble.directory](https://nimble.directory) with a 
database would be the best to implement browsing by categories or displaying 
tag clouds.

Meanwhile I created the [Curated 
Packages](https://github.com/nim-lang/Nim/wiki/Curated-Packages) page to 
provide hierarchical categories. As a wiki page, it is more user oriented than 
tool oriented, and it does not show other information like descriptions or 
licenses...


Re: Is it possible to browse the nimble.directory?

2019-12-08 Thread Stefan_Salewski
> lists each tag

Unfortunately not all packages have an optimal set of tags. For tagging, once 
my nimble publish was rejected due to too many tags, then I may had a nimble 
publish fail maybe because I typed the tags too slowly, then I tried gain with 
only one fast typed tag and nimble publish was successfull. So rtree package 
has only library tag I guess.

It would be fine if we could select from available tags when we publish a 
package, and maybe add a new one. And it would be nice if we could improve tags 
for our package. Maybe we can add tags to the .nimble file which each package 
has, so we have update tags with a git push?

And while we are talking about nimble -- the website entry seems not to work 
too nice. My rtree first got no website, while there is 
[http://ssalewski.de/tmp/rtree.html](http://ssalewski.de/tmp/rtree.html). Many 
packages have website entry identical to url as your


$ nimble search aporia
aporia:
  url: https://github.com/nim-lang/Aporia (git)
  tags:app, binary, ide, gtk
  description: A Nim IDE.
  license: GPLv2
  website: https://github.com/nim-lang/Aporia



Run

which is useless noise.

Does at least nimble search description takes content from .nimble file? Seems 
not really to work for me.

And for nimble search, would be nice if we get latest version number available 
and date of last update. 


Re: Is it possible to browse the nimble.directory?

2019-12-08 Thread dom96
You can introduce a page which lists each tag, sorted by how many packages are 
in that tag. This would already give a nice way to explore our packages.


Re: Is it possible to browse the nimble.directory?

2019-12-07 Thread SolitudeSF
nimble search


Re: Is it possible to browse the nimble.directory?

2019-12-07 Thread federico3
Unfortunately packages.json is not categorized and the tags are not based on 
structured classifiers, see 
[https://github.com/nim-lang/packages/pull/339](https://github.com/nim-lang/packages/pull/339)

I'd be happy to add browsing pages if we had categories or if the 
Curated-Packages had a machine-parsable format


Re: Is it possible to browse the nimble.directory?

2019-12-07 Thread marks
Thanks for your helpful replies: and to the others who've replied to my other 
questions.


Re: Is it possible to browse the nimble.directory?

2019-12-07 Thread Stefan_Salewski
See also

[https://github.com/nim-lang/Nim/wiki/Curated-Packages](https://github.com/nim-lang/Nim/wiki/Curated-Packages)

[https://github.com/VPashkov/awesome-nim](https://github.com/VPashkov/awesome-nim)


Re: Is it possible to browse the nimble.directory?

2019-12-07 Thread juancarlospaco
You can look here, is just a JSON 
[https://github.com/nim-lang/packages/blob/master/packages.json](https://github.com/nim-lang/packages/blob/master/packages.json)


Is it possible to browse the nimble.directory?

2019-12-07 Thread marks
The [https://nimble.directory](https://nimble.directory)/ has a good search 
function, but in reaquainting myself with nim I'd like to be able to see 
categories and browse. Is this possible?


Is it possible to use MbedTLS for HTTPS instead of OpenSSL?

2019-11-12 Thread LeFF
I need to write HTTPS client application, but I'd like to use MbedTSL 
(statically linked) for SSL/TLS support instead of OpenSSL. How can I hook it 
up so that Nim's HTTP protocol implementation would use MbedTLS? Thanks!


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-25 Thread Araq
I'm pretty sure this a regression, 
[https://github.com/nim-lang/Nim/issues/12516](https://github.com/nim-lang/Nim/issues/12516)


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-25 Thread Krux02
This is my solution to call functions by name: 
[https://github.com/krux02/opengl-sandbox/blob/master/examples/console.nim](https://github.com/krux02/opengl-sandbox/blob/master/examples/console.nim)

This example in this project does not have any dependentcies of that project 
itself, it should just work stand alone.


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread demotomohiro
I don't think nameToProc can be a compileTime variable because an address of 
procedure cannot be determined at compile time.


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread geohuz
Ok, I tried to remove compileTime pragma and it runs successfully, hope 
somebody can give me explanation.


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread geohuz
I tried to write the code (by following the manual):


import macros
import tables

var nameToProc {.compileTime.} = newTable[string, proc(): string 
{.nimcall.}]()

macro registerProc(p: untyped): untyped =
  result = newTree(nnkStmtList, p)
  
  echo repr(p[0])
  let procName = p[0]
  let procNameAsStr = $p[0]
  
  result.add quote do:
nameToProc.add(`procNameAsStr`, `procName`)


proc foo: string {.registerProc.} = "foo"
proc bar: string {.registerProc.} = "bar"
proc baz: string {.registerProc.} = "baz"


doAssert nameToProc["foo"]() == "foo"

Run

But I get the following error:


Error: unhandled exception: key not found: foo [KeyError]


Run


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread Araq
To expand on what mratsim said, you need to use an explicit string->proc lookup 
table. This table can be filled via a macro.


Re: Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread mratsim
proc names must be known at compile time. Use closures instead.


Possible to use identifier construction to call proc by name (string)?

2019-10-24 Thread geohuz
Just like in python/js, we have the following proc:


proc newAuthMessage() =
 ...

proc newSubscribeMessage() =
 ...

Run

and I want to call these procedures dynamically, so we have string "Auth" , 
"Subscribe", and now I need concatenate the string and call them. I tried with 
template but no luck. 


Re: strformat: using a ':' in a string literal possible?

2019-10-10 Thread MaineTim
Excellent! Thank you. 


Re: strformat: using a ':' in a string literal possible?

2019-10-09 Thread jyapayne
Ah, I see. I'm curious though why you want to put the raw string in the curly 
braces. You could do:


echo fmt("This is a string{colon:<30}Another String")


Run

There is also `alignLeft()` in the strutils module, but it's less attractive:


import strutils

echo "This is a string:".alignLeft(30) & "Another String"


Run


Re: strformat: using a ':' in a string literal possible?

2019-10-09 Thread jyapayne
Also, using a simple template, you could do:


import strutils

template `<`(str: string, padding: int): string =
  str.alignLeft(padding)

echo "This is a string:"<30, "Another String"


Run


Re: strformat: using a ':' in a string literal possible?

2019-10-09 Thread MaineTim
To follow myself up, this also "works", and requires only one variable 
definition for multiple fmt specs:


 let colon = ":"
 echo fmt("{\"This is a string\"}{colon:<30}{\"Another String\"}") 

Run


 This is a string: Another String


Run


Re: strformat: using a ':' in a string literal possible?

2019-10-09 Thread MaineTim
Hi @jyapayne \- Thanks for the quick response! Yes, that's the "workaround" 
I've taken to using, but it adds visual clutter if you're formatting a bunch of 
lines (which I am). Not a biggie, but I wondered if I was overlooking something.


Re: strformat: using a ':' in a string literal possible?

2019-10-09 Thread jyapayne
Seems like a bug to me. This works:


let str = "This is a string:"
echo fmt("{str:<30}")


Run


strformat: using a ':' in a string literal possible?

2019-10-09 Thread MaineTim
Another newbie question: is it possible to embed a ':' in a string literal in a 
fmt specification, as in: 


 echo fmt("{\"This is a string:\":<30}) 

Run

yields


 /usercode/in.nim(3, 10) Error: could not parse `"This is a string`.
 /nim/lib/core/macros.nim(540, 1) Error: closing " expected 

Run

Attempting to "escape" the colon: 


 echo fmt("{\"This is a string\:\":<30}) 

Run

yields 


 /usercode/in.nim(3, 31) Error: invalid character constant 

Run

How can I sneak a colon in there short of assigning the string to a variable?

Thanks! 


Re: Possible minor bug in unused import checker [1.0]

2019-09-25 Thread Wazubaba
Done. Sorry I'm kind of new to using Github issues.

Link for convenience: 
[https://github.com/nim-lang/Nim/issues/12259](https://github.com/nim-lang/Nim/issues/12259)


Re: Possible minor bug in unused import checker [1.0]

2019-09-24 Thread Araq
Thank you. Please report this issue on github.


Possible minor bug in unused import checker [1.0]

2019-09-24 Thread Wazubaba
Hi, signed up to post this. Congrats on achieving 1.0! My two current major 
projects already built just fine and in fact thanks to the unused imports 
message I was able to cull a bunch. I did however find a small problem. In one 
of them I have some modules which I export functionality from. The issue I 
found is that when one exports an imported module with a different name, i.e. 


import X as Y
export Y


Run

The compiler still warns about _X_ being an unused import, even if this is used 
in a module which imports this one.

Here's the minimal sample I confirmed this with: 
[https://anonfile.com/b3ueEe6an1/minimal_sample_zip](https://anonfile.com/b3ueEe6an1/minimal_sample_zip)


Re: Is it possible to detect context in relation to a threadvar?

2019-09-04 Thread Araq
I'm not sure, but maybe this helps a little:


let mainThread = getThreadId()

proc isMainThread(): bool = getThreadId() == mainThread


Run


Is it possible to detect context in relation to a threadvar?

2019-09-04 Thread JohnAD
I'm developing a library that maintains a global pool of resources that can be 
seen in both thread and non-threaded contexts. Rather than jump into great 
detail, let show this with a silly example:


import strutils
import jester

var someGlobal: string = "value at the moment"

var someThread {.threadvar.}: string

proc getSomeMain(): string =
  result = "copy of $1".format(someGlobal)

proc getSomeFromThread(): string {.gcsafe.} =
  someThread = "copy of $1".format(someGlobal)
  return someThread

someGlobal = "another change"

var x = getSomeMain()
echo x

routes:
  get "/":
var y = getSomeFromThread()
resp y


Run

Everything works great.

But, I ask, would it be possible to write a generic equivalent of "getSome". 
Something like:


proc getSome(): string =
  if MAGIC_DETECT_METHOD:
return "copy of $1".format(someGlobal)
  else:
someThread = "copy of $1".format(someGlobal)
return someThread


Run

Or, if not at runtime, some kind of compile-time thing that detects whether 
"getSome" is being called from a thread, such as a Macro or Template.

I apologize if the answer to this is well documented somewhere. I've not been 
able to find an answer yet. 


Re: possible in Nim

2019-08-30 Thread Araq
Hardly. You can do something like:


template `!foobar`(a) = echo a

`!foobar`("abc")



Run

But I fail to see the point.


possible in Nim

2019-08-29 Thread Kieutrang
Hello everyone, Is it possible in Nim to have a macro/template that starts with 
a custom character? For example, a macro like: #Declaration


Re: possible in Nim to have a macro/template

2019-08-26 Thread GordonBGood
@mratsim:

> with backticks...

That's really neat! I knew about backticks, but never thought of using them 
this way. Thanks.


Re: possible in Nim to have a macro/template

2019-08-26 Thread GordonBGood
@ScottTorres: a Julia fan, eh?

> is it possible in Nim to have a macro/template (name - GBG) that starts with 
> a custom character?

No, I don't think it's possible to start a macro name with anything other than 
a letter character as it would seem to be contrary [to the general naming of 
(any) identifiers in the 
manual](https://nim-lang.org/docs/manual.html#lexical-analysis-identifiers-amp-keywords)
 that they need to start with a letter


Re: possible in Nim to have a macro/template

2019-08-26 Thread mratsim
with backticks


macro `@myMacro`(): untyped =
  discard


Run


possible in Nim to have a macro/template

2019-08-25 Thread ScottTorres
Hello everyone, Is it possible in Nim to have a macro/template that starts with 
a custom character? For example, a macro like:

> #Declaration

macro @myMacro() :
... ...


Re: Is it possible to tune C output to be truly human readable?

2019-08-23 Thread mratsim
I think the main issue would be the use of gotos :P


Re: Is it possible to tune C output to be truly human readable?

2019-08-22 Thread treeform
Have you seen what the generated C/C++ code looks like?

Nim generated C code will use nim's seq and string implementation. I don't 
think you well get that passed C/C++ reviewers...


Re: Is it possible to tune C output to be truly human readable?

2019-08-22 Thread Araq
Well it's still C code, you can submit it for review and see what happens. ;-)


Is it possible to tune C output to be truly human readable?

2019-08-21 Thread dponyatov
As I understand, Nim produces C code just to be used as an interface with 
backend compiler.

Is it theoretically possible to tune code generation to make the generated code 
be accepted at code review in teams allows only C/C++ as a programming language 
for development? I mean, that some artifacts can be present, but code should be 
enough readable and editable if someone wants to do work with this code as a C 
source manually.


Re: Regex substitutions with Perl's syntax... possible with macros?

2019-07-14 Thread Araq
Yeah, it would be possible via macros, but I'm not sure what it should do? 
Replace and return true if there was a replacement?


Regex substitutions with Perl's syntax... possible with macros?

2019-07-13 Thread fredwagner
I know Nim already can do this (from documentation):


 line =~ re"\s*(\w+)\s*\=\s*(\w+)":
  # matches a key=value pair:
  echo("Key: ", matches[0])
  echo("Value: ", matches[1])
elif line =~ re"\s*(\#.*)":
  # matches a comment
  # note that the implicit ``matches`` array is different from the
  # ``matches`` array of the first branch
  echo("comment: ", matches[0])
else:
  echo("syntax error")

Run

What about the following syntax for regex substitution? Can it be emulated with 
macros ou added to the core language? 


string =~ s/regex/replacement/g;


Run

It would be great to have regex syntax sugar in the core language. That would 
make Nim even more practical, while still remaining readable.


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread stephenwithav
@yglukhov You're comment encouraged me to seek out a better ECS tutorial than 
the one I read prior to my first ECS(-ish). Thank you for that.

The tutorial, for anyone interested, is at: 
[http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1](http://t-machine.org/index.php/2007/09/03/entity-systems-are-the-future-of-mmog-development-part-1)/


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread stephenwithav
Thank you for the suggestion, @yglukhov. I'm familiar with ECS and have 
implemented one before in Go. I wanted to try the same in Nim to help me gain 
familiarity with the language.


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread yglukhov
@stephenwithav it's important to understand the problem ECS solves. ECS is 
notable for its memory utilization efficiency, gained from cpu-cache-friendly 
data layout. I'd suggest you read about that before implementing your ECS. But, 
small spoiler, neither polymorphic objects (interfaces), nor references are the 
options. At this point, i'd suggest not to consider variant objects either. :)


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread stephenwithav
Ideally, I'm hoping for something comparable to Golang interfaces.

I avoided C since the early '90s due to early compiler incompatibilities. Only 
recently, in the past few months, have I looked at C/C++ seriously.

Thank you for pointing to `variant`. I'm going to look at entt's source more 
closely and try to find a good equivalent in Nim. (I couldn't seem to make 
anything useful out of sequtils; Araq, I'm curious as to what you had in mind.)


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread Stefan_Salewski
> Then I learned this morning that seq[Component] fails.

That really should be obvious.

A seq in Nim is similar to vectors in C++, that is basically a plain C array 
that automatically resizes when necessary, where resize is new allocation and 
copying elements. So all elements must have same type and same size as in C 
arrays -- as all refs and pointers have the same size, we can have different 
ref types in a seq and can test for exact type with "of" operator at runtime.

Note that we have sum types (objects variants) in Nim. 


Re: Is something like EnTT possible with Nim?

2019-05-25 Thread stephenwithav
I thought I had something good last night:


type Position = object
  x: int
  y: int

type Velocity = object
  dx: int
  dy: int
  dz: int

type Component = Position | Velocity

proc showProps(p: Position) =
  echo p.x, ", ", p.y

proc showProps(v: Velocity) =
  echo v.dx, ", ", v.dy, ", ", v.dz

let p = Position(x: 9, y: 9)
let v = Velocity(dx: 1, dy: 1, dz: 3)

showProps(p)
showProps(v)


Run

While tedious, it was good.

Then I learned this morning that seq[Component] fails. _sigh_


 type Position = object
  x: int
  y: int

type Velocity = object
  dx: int
  dy: int
  dz: int

type Component = Position | Velocity

proc showProps(p: Position) =
  echo p.x, ", ", p.y

proc showProps(v: Velocity) =
  echo v.dx, ", ", v.dy, ", ", v.dz

let p = Position(x: 9, y: 9)
let v = Velocity(dx: 1, dy: 1, dz: 3)
var s: seq[Component]

s.add(p)
s.add(v)

echo s


Run


Re: Is something like EnTT possible with Nim?

2019-05-23 Thread stephenwithav
Thank you, Araq and doofenstein. I'm going to try to develop a VERY simple ECS 
today in Nim.

Somehow, I had totally missed (or forgotten) varargs and set. Those two should 
help make this first attempt successful.


Re: Is something like EnTT possible with Nim?

2019-05-23 Thread yglukhov
Another ECS attempt: 
[https://github.com/yglukhov/ecs](https://github.com/yglukhov/ecs)


Re: Is something like EnTT possible with Nim?

2019-05-22 Thread doofenstein
ha, you might be interested in this ECS implementation, from one of my failed 
Nim game engine attempts: 
[https://gist.github.com/RSDuck/6c8caf82aeb88991d440b228b3f32f06](https://gist.github.com/RSDuck/6c8caf82aeb88991d440b228b3f32f06)
 Note that this is mostly untested. For examples look at the bottom of the file.


Re: Is something like EnTT possible with Nim?

2019-05-22 Thread Araq
What's hard about `registry.view`? Please look at `sequtils.nim`.


Re: Is something like EnTT possible with Nim?

2019-05-21 Thread stephenwithav
assign shouldn't be too difficult... just add a subclass of Component to the 
seq.

But filtering for registry.view? I can't figure that one out yet. Templates, 
maybe?


Is something like EnTT possible with Nim?

2019-05-21 Thread stephenwithav
Specifically, I'm curious if tuples could take the place of structs, and 
equivalents for registry.assign and registry.view.

I can imagine registry as a seq[int], with each entity being represented by a 
unique integer, but I don't know how to assign tuples to an int.

I really like the ability to filter entities to only those with the specific 
components of interest. Is there a way to achieve the same in Nim?

[EnTT 
examples](https://github.com/skypjack/entt/blob/master/README.md#code-example)


  1   2   >