Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alias declarations #7090

Closed
wizzardx opened this issue Jan 16, 2018 · 15 comments
Closed

alias declarations #7090

wizzardx opened this issue Jan 16, 2018 · 15 comments
Labels

Comments

@wizzardx
Copy link
Contributor

More or less what you have in C, with the 'define' preprocessor directive, but in a type-safe manner.

This may be possible in eg a macro or template that could be added to stdlib.

Basically what D describes over here:
https://dlang.org/spec/declaration.html#alias

Meaning that eg, code like this (from Platformer tut):

proc handleInput(game: Game) =
  var event = defaultEvent
  while pollEvent(event):
    case event.kind
    of QuitEvent:
      game.inputs[Input.quit] = true
    of KeyDown:
      game.inputs[event.key.keysym.scancode.toInput] = true
    of KeyUp:
      game.inputs[event.key.keysym.scancode.toInput] = false
    else:
      discard

Can be expressed as something like this, for instance:

proc handleInput(game: Game) =
  alias inputs = game.inputs[event.key.keysym.scancode.toInput]
  var event = defaultEvent
  while pollEvent(event):
    case event.kind
    of QuitEvent:
      game.inputs[Input.quit] = true
    of KeyDown:
      inputs = true
    of KeyUp:
      inputs = false
    else:
      discard

It's possible currently to get a lot of these kinds of effects by making use of some combination of const or template, or inlined function, but it's a bit untidy or verbose.

Here's one basic example of it from the Nim forum:

https://forum.nim-lang.org/t/1515

It's also something that Ada lets you do with its "rename" syntax, eg:

http://www.adaic.org/resources/add_content/docs/95style/html/sec_5/5-7-2.html

https://en.wikibooks.org/wiki/Ada_Programming/Basic#"Hello,_world!"_with_renames

@ghost
Copy link

ghost commented Jan 16, 2018

This is possible with a template already, no?

@ghost
Copy link

ghost commented Jan 16, 2018

template inputs = game.inputs[event.key.keysym.scancode.toInput]

@wizzardx
Copy link
Contributor Author

Ah, thanks!
I've struggled with this in the past, too.
So in the linked forum thread, this solution would also work?

template bar = foo

@ghost
Copy link

ghost commented Jan 16, 2018

It probably will

@wizzardx
Copy link
Contributor Author

Doesn't look like it...

This works, as per forum thread:

proc foo(x: int) = echo x
const bar = foo
bar 10

This doesn't:

proc foo(x: int) = echo x
template bar = foo
bar 10

It gets this error:

test.nim(3, 5) Error: type mismatch: got (int literal(10))
but expected one of: 
template bar()

However, it looks like this does work, which is pretty nice:

proc foo(x: int) = echo x
template bar(x) = echo x
bar 10

@wizzardx
Copy link
Contributor Author

wizzardx commented Jan 16, 2018

However, this one sadly doesn't (it seems close to your original template example):

var a = 200
template b = a
b = 300
echo a

It gives this error:

test.nim(3, 1) Error: expression 'a' is of type 'int' and has to be discarded

This one does however:

var a = 200
let b = addr a
b[] = 300
echo a

However I think that syntax is a bit unsafe, ideally shouldn't be used.

I've edited that forum thread with this updated info.

@jcosborn
Copy link
Contributor

You need to declare the return value. The error is saying that a returns an int, but it wasn't expecting any return value.

var a = 200
template b: untyped = a
b = 300
echo a

@wizzardx
Copy link
Contributor Author

wizzardx commented Jan 17, 2018

Ah, thanks, that helps a lot!

There's a section in the Nim manual which talks about untyped:

https://nim-lang.org/docs/manual.html#overloading-resolution-lazy-type-resolution-for-untyped

But it's not immediately obvious from that, that you can use template to swap in the left hand side of an assignment.

However, looks like I can't say eg, substitute a proc directly:

proc foo(x, y, z: int) =
  echo x + y + z

template bar: untyped = foo

bar(1,2,3)

Or eg rename modules, eg like this:

import os

echo os.fileExists("/tmp/")

template my_os: untyped = os

echo my_os.fileExists("/tmp/a.txt")

I think I'm asking for something pretty close to a source code string substitution macro, eg something like this, where "aliasing" is the macro, and "alias" is a special identifier recognized by the macro, like this:

(kind of, operating a lot like how C's "define" preprocessor directive works):

aliasing:

  # os is a module
  alias(my_os, "os")
  echo my_os.fileExists("/")  # Same as: echo os.fileExists("/")

  # bar is a function
  alias(foo, "bar")
  foo(1, 2, 3, 4, "abcd")  # Same as: bar(1, 2, 3, 4, "abcd")

  # a is a variable
  alias(b, "a")
  var a: int
  b = 123        # Same as: a = 123

  # x.a.b is a structure, where b is a seq.
  alias(s, "x.a.b[idx]")
  var idx = 999
  s = 123        # Same as: x.a.b[idx] = 123

@jcosborn
Copy link
Contributor

The proc example can be done too. Note that specifying a return type (which can also be untyped) is only necessary if it returns a value.

proc foo(x, y, z: int): int =
  x + y + z
proc foo2(x, y, z: int) =
  echo foo(x, y, z)
template bar(v: varargs[untyped]): untyped = foo(v)
template bar2(v: varargs[untyped]) = foo2(v)
echo bar(1,2,3)
bar2(1,2,3)

I don't think there is a solution for the module alias at the moment.

@ghost
Copy link

ghost commented Jan 17, 2018

@wizzardx @jcosborn

import os as my_os
echo my_os.fileExists("hello")

Module aliasing IS possible :)

@jcosborn
Copy link
Contributor

Ah, yes, and that even works in addition to other import names.

import os
import os as my_os
echo os.dirExists("/tmp")
echo my_os.dirExists("/tmp")

@Araq
Copy link
Member

Araq commented Jul 1, 2018

Workarounds have been sorted out. Closing.

@timotheecour
Copy link
Member

the workarounds don't work in many cases; this issue is properly fixed here: #11822

@dom96
Copy link
Contributor

dom96 commented Jul 25, 2019

@timotheecour I'm going to repeat my request again, please stop cross-referencing your PRs across every single related issue. You can see that GitHub shows that you've referenced this issue above. Writing a comment here is just noise in our notifications.

@timotheecour
Copy link
Member

timotheecour commented Jul 25, 2019

sure, will do. my reasoning was that issues may be referenced in a PR, but the PR is not intending to fix or close the issue referenced (eg workaround or just part of PR description). But fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment