What's the future of "implicitDeref"?

2020-06-27 Thread exelotl
When doing manual memory management in Nim, I often find myself having to 
define two versions of a proc - one that takes a `var` parameter and one that 
takes a `ptr` parameter.

Otherwise I will run into issues like this:


var m: ptr Monster
var b: Bullet

proc chooseAnim(m: var Monster) =
  # some logic to set the current animation
  # ...

proc update(b: ptr Bullet) =
  # move the bullet and check for collisions
  # ...

m.chooseAnim()  # uh oh!
m[].chooseAnim()  # better.

b.update() # uh oh!
(addr b).update()  # better.


Run

I was happy to discover that [{.experimental: 
"implicitDeref".}](https://nim-lang.org/docs/manual.html#types-reference-and-pointer-types)
 is a thing, which pretty much fixes all my problems! If I define the `var` 
version of the procedure, I don't need to define the `ptr` version anymore.

But I suppose I can't start doing this in library code yet, because then I'd be 
forcing other people to use this experimental pragma in their code, or to have 
to worry about addressing/dereferencing their stuff to make the library 
functions happy.

So I was wondering, what's the future of this feature? Do we know yet if it's 
here to stay? Does it have any caveats that I should know about?

Thanks :)


Re: Procedure overloading with explicit parameters

2020-06-25 Thread exelotl
I guess it's just semantically not how Nim works.

A proc has 1 body. However, if you use static/generic parameters then different 
versions of the proc body will be generated at compile-time based on the input.


proc say(n: static int) =
  when n == 1:
echo "static one!"
  else:
echo "static " & $n

proc say(n: int) =
  echo "dynamic " & $n

var x = 3

say(1) # --> static one!
say(2) # --> static 2
say(x) # --> dynamic 3


Run

(under the hood I believe 3 different procedures will be generated here, two of 
them are different variations of the first proc)

But you can't implement your factorial example with this, because choosing 
whether to return '0' or 'n*fac(n-1)' is a runtime decision.


Re: Uncle Bob - one syntax to rule them all?

2020-06-02 Thread exelotl
Ironically I don't think Uncle Bob would like Nim at all, given our general 
preferance towards straightforward "get shit done" procedural code. For example 
in [this video](https://youtu.be/IRTfhkiAqPw?t=1179) the author critiques some 
of Bob's code and rewrites it in a simple procedural style. The resulting code 
is far more like what I would expect to see in a Nim codebase.


Re: Lambda syntax is awkward

2020-06-02 Thread exelotl
There are some solutions, but all a little awkward.

1\. ["do" 
notation](https://nim-lang.org/docs/manual_experimental.html#do-notation), 
which I believe was moved to _experimental_ just before Nim 1.0, therefore 
might be changed or scrapped in a future Nim version.

Personally I think it's even harder to read than the plain `proc` version. 


let plusTwo = twice(10) do (n:int) -> int:
  echo "Another gratuitious echo"
  n + 1


Run

2\. Sugar module with a [statement list 
expression](https://nim-lang.org/docs/manual.html#statements-and-expressions-statement-list-expression)
 where the last expression in the brackets is treated as the value.

Not idiomatic, wouldn't recommend. 


let plusTwo2 = twice(10, n => (
  echo "Another gratuitious echo";
  n + 1
))


Run

3\. Sugar module with a [block 
expression](https://nim-lang.org/docs/manual.html#statements-and-expressions-block-expression).

I almost like this one! Unfortunately if you remove the brackets, you get " 
_Error: expression expected, but found 'keyword block'_"


let plusTwo3 = twice(10, n => (block:
  echo "Another gratuitious echo"
  n + 1
))


Run

Does anyone know, is this a syntax limitation, or could the `=>` operator be 
modified to allow a block expression without brackets? 


Re: Can the nim compiler run in the browser? Experimenting Nim to template web pages

2020-06-01 Thread exelotl
This is looking absolutely stellar! Have really wanted something like this, was 
thinking of making my own but didn't know where to start. I'm definitely gonna 
try this out :)


Re: Raylib Forever (4Nim)

2020-02-26 Thread exelotl
This is cool! I gave it a spin and it Just Worked™ with the latest raylib dll, 
very painless experience :)

Some thoughts:

As neat as this generator page is, I'd rather have a regularly updated nimble 
package. But hey, you've already done the hard part! Maintaining such a package 
would be a lot easier thanks to your script.

The function names should absolutely change. Pretty much every Nim programmer 
would rather write `initWindow` than `InitWindow`

It might be nice to use `##` instead of `#` for documentation comments, so that 
people can have nice helpful tooltips when their editor supports nimsuggest.

Anyways, thanks a bunch, you've done a great job so far.


Re: Discord server improvements

2020-01-21 Thread exelotl
Hey, can we make this happen? I use Discord a lot and would love to see the Nim 
server expanded. I feel like the community is big enough now for it work.


Re: Advent of Nim 2019 megathread

2019-12-01 Thread exelotl
doin' it 
[https://github.com/exelotl/aoc2019](https://github.com/exelotl/aoc2019)


Re: let & const on C backend

2019-11-10 Thread exelotl
> Then, I need to import this C var into nim? This does not look like a good 
> idea.

Yeahh, in my project I'm using this pattern all over the place, because it's 
basically the only option right now. It works but it's cumbersome, I'm looking 
forward to the day when Nim has a proper solution to this.

I think implementing a `{.readonly.}` pragma for `let` variables is the best 
course of action. Having the compiler auto-detect cases where the readonly 
codegen can be applied would be a nice extra, but I don't think it really adds 
much. As embedded users, I think we would prefer to be explicit about these 
things, right?

At some point Araq said _" You write an RFC, we implement it."_ so I did, but 
then that changed to _" you implement it"_ which uh, I'm not against trying but 
I don't think I can find the time for it right now. If someone more experienced 
with the Nim codebase could take over and get this done, I'd really appreciate 
it.


Re: Feature Request: Addressable Constants

2019-09-18 Thread exelotl
Yep, I chatted to Araq about this yesterday on IRC, and he arrived at the same 
conclusion. I'll submit an issue for it later today :)


Re: Feature Request: Addressable Constants

2019-09-17 Thread exelotl
Yes, I was not suggesting that Nim should disallow it, but that _if arr was 
generated as const in C_ then it should fail to compile at the C stage. And 
that should be acceptable behaviour, since I used `unsafeAddr` after all, and 
Nim has made no promises about arr being mutable.


Feature Request: Addressable Constants

2019-09-14 Thread exelotl
Hey! For several months I've been working on a Game Boy Advance game in Nim. 
This has been a great experience for the most part. For example I used macros 
to hugely reduce the amount of boilerplate required to load and draw sprites, 
preventing a lot of human errors with no performance cost.

However there is one place where I feel the language is really lacking, for 
which I've not yet found any good solution. That is: addressable constant data.

The GBA has very little RAM. So if you have any data that doesn't change 
(graphics, palettes, tile maps, level data, animation data, lookup tables, 
etc.), you'll want to store it in ROM. In C, you do this by marking your data 
as 'const', which will cause the compiler to put it in the .rodata section of 
the ELF.

The problem is, Nim has no concept of a 'pointer to constant data'. Nim consts 
only exist at compile time. You can get a pointer once the const has been 
copied into a variable, but there simply isn't enough memory to do that on 
embedded platforms.

Meanwhile if your constant data comes from the C side, you can use {.importc.} 
to access it. But Nim doesn't know that this data is supposed to be constant. 
If you take a pointer to it, Nim won't stop you from mutating it by accident. 
You'll also find yourself getting a lot of warnings such as "initialization 
discards 'const' qualifier from pointer target type".

I've tried a lot of different solutions, none of them are great:

  * For const cstrings and raw binary data in Nim, I can import the '&' 
operator from C and use it to get the address of the string. This is an awful 
hack, but it works because the string will be embedded in-place in the 
generated C code, and we can rely on the C compiler to optimise away any 
duplicate occurrences. 

proc `&`*[T](x:T):ptr T {.importc:"&", nodecl.}
const data:cstring = staticRead("data.bin")
var p = &(data[39])  # get a pointer to the 40th byte

Run

  * For const objects in Nim, I can use {.exportc.} on the type, {.emit.} the 
data as C code, and then import the object back into Nim. But this is an 
absolute pain to maintain and you have to jump through a lot of hoops to get it 
working. The following isn't very usable because nodecl means the variable 
inaccessible from other modules. 

{.emit:"static const LevelData lvl1 = {...};".}
var lvl1: {.importc, nodecl.}: LevelData
var currentLevel = addr lvl1

Run

  * For const data that already exists on the C side, I can just use importc, 
but sometimes it's not practical to move my data to the C side (especially for 
cases where the relevant values are only available in Nim, such as procedure 
lookup tables)



In summary, I'm experiencing a lot of pain trying to express something that Nim 
doesn't know how to express. Addressable constants are really important for 
embedded programming. I think the language is in need of some additional 
construct to support this.

Some ideas:

  1. an {.addressable.} pragma for consts which guarantees them to have a 
location in the generated C code, and allows 'unsafeAddr' to work with them
  2. a {.readonly.} pragma for variables which makes them fully immutable and 
forces them to be const in C
  3. a const modifier for types? This would be like the {.readonly.} pragma 
above, but apply to any variable of that type. It could also make pointers to C 
consts safer and eliminate the warnings from the C compiler.



Let me know what you think :)