Re: Go-lang like interface

2017-10-19 Thread doofenstein
This thread is a bit dusty, but I just want to mention, that I made some 
improvements to andrea's implementation, in case somebody is still interested 
in interfaces like this, while vtrefs are still unimplemented.

Mainly I fixed it(previously the generated AST was invalid) and added a way to 
export interfaces. I've already made a [pull 
request](https://github.com/andreaferretti/interfaced/pull/1).


Re: Go-lang like interface

2017-01-27 Thread Krux02
Go ahead and publish it however you want. I mean this is some form of 
publishing, it is just not a git repository. I don't claim any patents here, I 
published it so it could get spread around the world. If you want to, you could 
add a link that says that you got inspired by this thread, then I might add a 
link to your version in the initial post.


Re: Go-lang like interface

2017-01-27 Thread andrea
A minor minor variant that works with `var` parameters instead of `ptr`:


import macros

macro implementInterface(interfaceName: typed) : untyped =
  let
interfaceNameStr = $interfaceName.symbol
vtableSymbol = interfaceName.symbol.getImpl[2][2][1][1][0]
vtableRecordList = vtableSymbol.symbol.getImpl[2][2]
  
  let
objectConstructor = nnkObjConstr.newTree(vtableSymbol)
  
  for identDefs in vtableRecordList:
let
  methodName = identDefs[0]
  params = identDefs[1][0]
  lambdaBody = quote do:
cast[var T](this).`methodName`()
  call = lambdaBody[0]

for i in 2 ..< len(params):
  let param = params[i]
  param.expectKind(nnkIdentDefs)
  for j in 0 .. len(param) - 3:
call.add param[j]

# leave out () when not needed
if call.len == 1:
  lambdaBody[0] = call[0]

methodName.expectKind nnkIdent

objectConstructor.add nnkExprColonExpr.newTree(
  methodName,
  nnkLambda.newTree(
newEmptyNode(),newEmptyNode(),newEmptyNode(),
params.copy,
newEmptyNode(),newEmptyNode(),
lambdaBody
  )
)
  
  let
getVtableReturnStatement =
  nnkReturnStmt.newTree(newCall("addr", newIdentNode("theVtable")))
globalVtableIdent = newIdentNode("theVtable")
getVtableProcIdent = newIdentNode("get" & interfaceNameStr & "Vtable")
getVtableProcDeclaration = quote do:
  proc `getVtableProcIdent`[T](): ptr BananasVtable =
var `globalVtableIdent` {.global.} = `objectConstructor`
`getVtableReturnStatement`
  
  result = newStmtList()
  result.add getVtableProcDeclaration
  
  let castIdent = newIdentNode("to" & $interfaceName.symbol)
  
  result.add quote do:
converter `castIdent`[T](this: ptr T) : `interfaceName` = 
`interfaceName`(
  objet : this,
  vtable : `getVtableProcIdent`[T]()
)
  
  result.add quote do:
converter `castIdent`[T](this: var T) : `interfaceName` = 
`interfaceName`(
  objet : this.addr,
  vtable : `getVtableProcIdent`[T]()
)
  
  result.add quote do:
converter `castIdent`(this: `interfaceName`): `interfaceName` = this
  
  when defined(interfacedebug):
echo result.repr


macro createInterface*(name : untyped, methods : untyped) : untyped =
  name.expectKind nnkIdent
  
  
  let
nameStr = $name.ident
vtableRecordList = nnkRecList.newTree
vtableIdent = newIdentNode(nameStr & "Vtable")
vtableTypeDef = nnkTypeSection.newTree(
  nnkTypeDef.newTree(
vtableIdent,
newEmptyNode(),
nnkObjectTy.newTree(
  newEmptyNode(),
  newEmptyNode(),
  vtableRecordList
)
  )
)
  
  var newMethods = newSeq[NimNode]()
  
  for meth in methods:
meth.expectKind(nnkProcDef)
let
  methodIdent = meth[0]
  params = meth[3]
  thisParam = params[1]
  thisIdent = thisParam[0]
  thisType  = thisParam[1]

if thisType != name:
  error thisType.repr & " != " & name.repr

let vtableEntryParams = params.copy
vtableEntryParams[1][1] = newIdentNode("pointer")

vtableRecordList.add(
  nnkIdentDefs.newTree(
methodIdent,
nnkProcTy.newTree(
  vtableEntryParams,
  newEmptyNode(),
),
newEmptyNode()
  )
)

let call = nnkCall.newTree(
  nnkDotExpr.newTree( nnkDotExpr.newTree(thisIdent, 
newIdentNode("vtable")), methodIdent  ),
  nnkDotExpr.newTree( thisIdent, newIdentNode("objet") ),
)

for i in 2 ..< len(params):
  let param = params[i]
  param.expectKind(nnkIdentDefs)
  for j in 0 .. len(param) - 3:
call.add param[j]

meth[6] = nnkStmtList.newTree(call)

newMethods.add(meth)
  
  result = newStmtList()
  result.add(vtableTypeDef)
  result.add quote do:
type `name` = object
  objet : pointer
  vtable: ptr `vtableIdent`
  
  for meth in newMethods:
result.add meth
  
  result.add newCall(bindSym"implementInterface", name)
  
  when defined(interfacedebug):
echo result.repr


Usage:


import interfacemacros

type
  MyBananas = object
a,b : int
  OtherBananas = object
foo,bar: int

proc foo(banan : var MyBananas) : int =
  banan.a + banan.b

proc bar(banan : var MyBananas) : int =
  banan.a * bana

Re: Go-lang like interface

2016-08-21 Thread Krux02
@Udiknedormin

What you call inheritance I would, if I do implement it, rather do as embedding.


createInterface BeautyGenerator:
  HealthGenerator
  EnergyGenerator
  proc genBeauty(g: BeautyGenerator): Beauty


You can se Go type embedding for example.This would create implicit conversions 
to HealthGenerator and EnergyGenerator. I think it's possible with not too much 
effort, which doesn't mean that I will implement it now.


Re: Go-lang like interface

2016-08-20 Thread Tarmean
My use cases would be virtually identical to the vtable usage of the standard 
library for things like streams. I just find that syntax extremely annoying and 
would love to have it abstracted away without having additional runtime costs.

In my perfect world this would be an addition to concepts, so that they can 
either make the function implictely generic as they do now or do dynamic 
dispatch via implicitely generated vtable.

With that said I also would prefer the pointers to be dereferenced before the 
proc is called. That way keeping it alive out of scope would be save and you 
still could use a var param to get it mutably. That way interfaces would also 
mirror the static duck typing awesomeness and clean syntax you generally have 
in nim while also having the advantages of dynamic dispatch where necessary.

Finally, I do agree that type reflectoon on interfaces doesn't really seem 
necessary. The tight coupling seems to remove the whole purpose the interface 
had in the first place. An if you aren't interested in that there are, like, 
three other ways to do the same thing with less overhead and ugly hacks. Any 
use case that couldn't be solved with variant types, methods or generics more 
cleanly?


Re: Go-lang like interface

2016-08-20 Thread Udiknedormin
What's a pity _interface_ is a keyword so it can't be used for declaring 
interfaces.

Interfaces can become particularly handy if used as a result type, it seems to 
me. Either way, it would be great to provide interface inheritance:


createInterface HealthGenerator:
  proc genHealth(g: HealthGenerator): Health

createInterface EnergyGenerator:
  proc genEnergy(g: EnergyGenerator): Energy

createInterface BeautyGenerator of HealthGenerator, EnergyGenerator:
  proc genBeauty(g: BeautyGenerator): Beauty

type
  Pear = ...

proc genHealth(g: Pear): Health = ...
proc genEnergy(g: Pear): Energy = ...
proc genBeauty(g: Pear): Beauty = ...

let pear = Pear(...)

let beautifier: BeautyGenerator = pear   # vtable's pointer points at p
echo beautifier.genEnergy()
echo beautifier.genHealth()
echo beautifier.genBeauty()

let energiser: EnergyGenerator = beautifier  # new vtable's pointer still 
points at p
echo energiser.genEnergy()
#echo energiser.genHealth()  # but has other procedure 
pointers
#let other: BeautyGenerator = energiser  # so the information is lost


Making the converter interfaces-aware so that vtables aren't pointed but 
partially copied sounds easy as all the converter has to do is:

  * recognize the argument as an interface (interfaces inheriting from common 
type, easy)
  * check if all of the input interface's subroutines are present in the output 
interface



A simple compile-time procedure returning bool value is all the converter needs.

A runtime time label for interfaces sounds like an interesting idea but let's 
see what happens when we provide them: 


let
  pear = Pear(...)
  beautifier: BeautyGenerator = pear
  energiser:  EnergyGenerator = beautifier
  other:  BeautyGenerator = energiser.getType()

if beautifier.realType of Pear:
  pearLover.eat(cast[ptr Pear](beautifier.obj)[])


getType() can't return the real type but a mere label. Still, if it can be used 
to retrieve the full type through a pointer cast, why not convert it to another 
(possibly wider) interface? 


proc burn(g: EnergyGenerator): Energy =
  result = g.genEnergy()
  if g.getType of SmokeGenerator:
toSmokeGenerator(g).genSmoke()


Well, it looks good, right? Well, it does if we forgot about memory usage. 
Notice that if any cast between the label and an interface label's type fulfils 
is valid at runtime, then it means all the subroutine pointers for that type 
must reside in memory. Not so funny if using a "popular" type.

Which is why it sounds more reasonable to either not provide any type label at 
all or provide it only for explicit type casts, NOT conversions to other 
interfaces, which isn't obvious and may be confusing for some users if 
type-switch or similar transparent real-type-getters will be available.


Re: Go-lang like interface

2016-08-16 Thread Krux02
@andrea I will test it a bit more and make sure that id doesn't have obvious 
bugs. I am also thinking of using concepts to make sure only data can be casted 
to an interface type that actually is compatible, and get nice error messages 
in case it doesn't work. Also the type switch or emty interface is not 
implemented yet.

@Sixte I think I once read that blog. That blog supported me in my decision to 
not get stuck in the Go programming language, and keep searching for the best 
programming language. I put a lot of hope into the Rust programming language 
afterwards, and was hugely disappointed when I explored the macro capabilities. 
Then I found Nim was very enthusiastic. And even though, I think Go is a very 
limiting programming language, I really like it for it's simplicity and the 
very powerful intarface type. Then I thought if I could have the interface type 
of Go in Nim, it would be awesome. And then I did it. Even though I found lot's 
of bugs in Nim, I really like this language.


Re: Go-lang like interface

2016-08-16 Thread Sixte
Some sceptical thoughts about the go language:

"Why Go Is Not Good"

[http://yager.io/programming/go.html](http://forum.nim-lang.org///yager.io/programming/go.html)

audiatur et altera pars ^^


Re: Go-lang like interface

2016-08-16 Thread Krux02
@Tarmean I now also did what you did, and I am posting my code here. I don't 
update the original post, because it would require me to either update the 
entire code there and rewrite things, or break compatibility with the example 
and the macro code. So I just post it here:


import macros

macro implementInterface(interfaceName: typed) : untyped =
  let
interfaceNameStr = $interfaceName.symbol
vtableSymbol = interfaceName.symbol.getImpl[2][2][1][1][0]
vtableRecordList = vtableSymbol.symbol.getImpl[2][2]
  
  let
objectConstructor = nnkObjConstr.newTree(vtableSymbol)
  
  for identDefs in vtableRecordList:
let
  methodName = identDefs[0]
  params = identDefs[1][0]
  lambdaBody = quote do:
cast[ptr T](this).`methodName`()
  call = lambdaBody[0]

for i in 2 ..< len(params):
  let param = params[i]
  param.expectKind(nnkIdentDefs)
  for j in 0 .. len(param) - 3:
call.add param[j]

# leave out () when not needed
if call.len == 1:
  lambdaBody[0] = call[0]

methodName.expectKind nnkIdent

objectConstructor.add nnkExprColonExpr.newTree(
  methodName,
  nnkLambda.newTree(
newEmptyNode(),newEmptyNode(),newEmptyNode(),
params.copy,
newEmptyNode(),newEmptyNode(),
lambdaBody
  )
)
  
  let
getVtableReturnStatement =
  nnkReturnStmt.newTree(newCall("addr", newIdentNode("theVtable")))
globalVtableIdent = newIdentNode("theVtable")
getVtableProcIdent = newIdentNode("get" & interfaceNameStr & "Vtable")
getVtableProcDeclaration = quote do:
  proc `getVtableProcIdent`[T](): ptr BananasVtable =
var `globalVtableIdent` {.global.} = `objectConstructor`
`getVtableReturnStatement`
  
  result = newStmtList()
  result.add getVtableProcDeclaration
  
  let castIdent = newIdentNode("to" & $interfaceName.symbol)
  
  result.add quote do:
converter `castIdent`[T](this: ptr T) : `interfaceName` = 
`interfaceName`(
  objet : this,
  vtable : `getVtableProcIdent`[T]()
)
  
  result.add quote do:
converter `castIdent`[T](this: var T) : `interfaceName` = 
`interfaceName`(
  objet : this.addr,
  vtable : `getVtableProcIdent`[T]()
)
  
  result.add quote do:
converter `castIdent`(this: `interfaceName`): `interfaceName` = this
  
  echo result.repr


macro createInterface*(name : untyped, methods : untyped) : untyped =
  name.expectKind nnkIdent
  
  
  let
nameStr = $name.ident
vtableRecordList = nnkRecList.newTree
vtableIdent = newIdentNode(nameStr & "Vtable")
vtableTypeDef = nnkTypeSection.newTree(
  nnkTypeDef.newTree(
vtableIdent,
newEmptyNode(),
nnkObjectTy.newTree(
  newEmptyNode(),
  newEmptyNode(),
  vtableRecordList
)
  )
)
  
  var newMethods = newSeq[NimNode]()
  
  for meth in methods:
meth.expectKind(nnkProcDef)
let
  methodIdent = meth[0]
  params = meth[3]
  thisParam = params[1]
  thisIdent = thisParam[0]
  thisType  = thisParam[1]

if thisType != name:
  error thisType.repr & " != " & name.repr

let vtableEntryParams = params.copy
vtableEntryParams[1][1] = newIdentNode("pointer")

vtableRecordList.add(
  nnkIdentDefs.newTree(
methodIdent,
nnkProcTy.newTree(
  vtableEntryParams,
  newEmptyNode(),
),
newEmptyNode()
  )
)

let call = nnkCall.newTree(
  nnkDotExpr.newTree( nnkDotExpr.newTree(thisIdent, 
newIdentNode("vtable")), methodIdent  ),
  nnkDotExpr.newTree( thisIdent, newIdentNode("objet") ),
)

for i in 2 ..< len(params):
  let param = params[i]
  param.expectKind(nnkIdentDefs)
  for j in 0 .. len(param) - 3:
call.add param[j]

meth[6] = nnkStmtList.newTree(call)

newMethods.add(meth)
  
  result = newStmtList()
  result.add(vtableTypeDef)
  result.add quote do:
type `name` = object
  objet : pointer
  vtable: ptr `vtableIdent`
  
  for meth in newMethods:
result.add meth
  
  result.add newCall(bindSym"implementInterface", name)
  
  # optional if you want to see what you generated
  # echo result.repr



And here is an example how to use it. Doesn't make a lot of sense, but yea it's 
just to show that it 

Re: Go-lang like interface

2016-08-10 Thread Krux02
That `{.global.}` usage is in fact pretty cool. I did not know of this 
behavior, but it makes sense, because static variables in c++ behave the same 
way. I guess I should use it, too.


Re: Go-lang like interface

2016-08-09 Thread Tarmean
Oh, forgot to re-add the unsafeaddr when returning, I had it removed to test 
the speed difference. The {.global.} variable is instantiated once for each 
type the generic proc is instantiated with, I think that is a way to get around 
having to call implementInterface.

usage with macro then looks like this:


defInterface Foo:
  proc bar(this: Foo): int
type
  A = object
  B = object
x: int
proc bar(this: ptr A): int = 3
proc bar(this: ptr B): int = this.x
var
  a = A()
  b = B(x: 5)
  a_i = a.toFoo()
  b_i = b.toFoo()
  
  collection = @[a_i, b_i]
for entry in collection:
  echo entry.bar()


On my first try I screwed up the vtable for procs with additional arguments but 
I think I fixed that. Macro ended up being very similar to yours, though.


Re: Go-lang like interface

2016-08-09 Thread Krux02
I am not sure if it is intentional, but it looks like a bug: Why is `table` 
here global?


let table {.global.} = MethodTable(
foo: proc (this:pointer):int = cast[ptr T](this).foo
)


EDIT:

Btw that is the same way I started. I wrote a version that works without 
macros, and then I wrote a marco that would generate all the parts that could 
be automated.


Re: Go-lang like interface

2016-08-08 Thread Tarmean
Very cool idea! Tried to allow the interface to be implemented implicitly:


type
  Interface = object
obj: pointer
vtable: MethodTable
  MethodTable = object
foo: proc(this: pointer): int

proc toInterface[T](t: var T): Interface =
  let this = addr t
  let table {.global.} = MethodTable(
foo: proc (this:pointer):int = cast[ptr T](this).foo
)
  result =  Interface(obj: this, vtable: table)
proc foo(this: Interface): int =
  this.vtable.foo(this.obj)

type
  A = object
  B = object
proc foo(a: ptr A): int = 3
proc foo(a: ptr B): int = 5
var
  a = A()
  b = B()
  a_i = toInterface(a)
  b_i = toInterface(b)
  c = @[a_i, b_i]
for e in c:
  echo e.foo()


Works with two caveats: If toInterface is a converter and you try to use it 
implicitly nim generates illegal c code. And if toInterface is defined after 
exactly one implementation of foo() it breaks with

> type mismatch: got (ptr A) but expected one of: proc foo(this: Interface): int

If toInterface is a converter nim just straight up hangs up. If toInterface 
comes first or at least two foo()'s are defined before it everything works fine.


Re: Go-lang like interface

2016-08-07 Thread Krux02
@OderWat that's the hard part, finding a good real world example. Real world 
example are most of the time either too complicated for an example or not 
suitable, because they have a simpler or better solution, which does not use 
this interface implementation. And then there is also the risk that the example 
is from a domain the reader will probably not understand. A really good example 
is an example where the interface type is superior to both the inheritance 
based approach, **and** the generics based approach.

**Better than Generics:**

  * the function `foobar` should be somewhat complex, so that not using 
generics actually is an advantage. This could be done by having a complex macro 
call in the body that could eat some time of the compiler. You should know that 
a macro is evaluated after the generic instanciation.



**Better than inheritance**

  * At least one interface implementation is part of some older library, where 
the auther that writes the interface has no acces to, and therefore can't add 
inheritance.
  * Or, the objects need to be very compact, so that adding a vtable to each 
object is a bad idea.




Re: Go-lang like interface

2016-08-07 Thread OderWat
I think it would be easier to understand the code and the idear behind it if it 
would not use "MyInterface" and "MyImplementationX". I don't know how that is 
for other people by I would prefer them named after a (constructed) real world 
example instead.


Re: Go-lang like interface

2016-08-07 Thread dom96
This is a nice post, thanks for sharing.

> This is not a question, more like a blog post. I don't have a blog so I do it 
> here. Feel free to comment or ask questions.

I'm thinking it would be nice to start doing what D is doing: guest blog 
articles. I recently modified the website so that articles are standalone, 
turning it into a viable blog. Would you be interested in having this posted on 
[http://nim-lang.org](http://forum.nim-lang.org///nim-lang.org)? 


Re: Go-lang like interface

2016-08-06 Thread OderWat
Just if anybody wants / needs to know how to modify @Krux02 original code to 
automatically use a converter and therefor hiding more of the implementation 
details.

Simply replace the lines from `let castIdent = ...` to the end of the file with:


# instead of let castIdent = ...
  let converterIdent = newIdentNode($interfaceName.symbol & "Converter")
  
  result.add quote do:
converter `converterIdent`(this: var `implementationCandidateName`) : 
`interfaceName` = `interfaceName`(
  objet : this.addr,
  vtable : `vtableValueSymbol`.unsafeAddr
)



The example can simply call `foobar(a)` and `foobar(b)` after this modification.


Re: Go-lang like interface

2016-08-06 Thread Krux02
@andrea

Of course you are allowed to use this code, and I actually thought about 
putting it on github so it is more accessable to people. I am not so sure about 
the nimble package at this point in time. I will think about it.


Re: Go-lang like interface

2016-08-05 Thread andrea
@Krux02 It would be really nice to have these macros published on Nimble!


Re: Go-lang like interface

2016-08-03 Thread _tulayang
@bpr

> That sounds like an anti-feature to me, kind of like the anti-feature of 
> Python (discussed on another thread here) that allows one to add object 
> attributes at any time.

In Scala, Rust and more modern language, you can change external variable in 
funcational programming.

And, this is why there are var parameters when you define Nim proc.

No side effects will get lowwer performance. 


Re: Go-lang like interface

2016-08-03 Thread _tulayang
@Krux02

> Yes, and you are ignorant to learn about them.

HAHA. I don't learn about Golang because Golang is a lousy language.

There are so many good languages better than Golang: C, Nim, Rust, Erlang, 
Scala, Java, Scheme.

> Yes, live with it.

"Pure function" are not realistic. Did you know Lisp is a functional 
programming language? 


Re: Go-lang like interface

2016-08-03 Thread cdunn2001
GoLang compilation recently took a big hit (2x to 10x slower for various apps) 
when the compiler was re-written from C to bootstrapped Go. Rob Pike was 
concerned, which I think is a good sign. With Go-1.7, it is almost as fast as 
1.5 again.

D2 on the other hand, though still fast, is quite a bit slower than D1.

Here is a bit on how templates and other things were sped up in the D compiler:

  * 
[http://www.drdobbs.com/cpp/increasing-compiler-speed-by-over-75/240158941](http://forum.nim-lang.org///www.drdobbs.com/cpp/increasing-compiler-speed-by-over-75/240158941)



One huge advantage of Nim and D over C++ is that a template specialization is 
instantiated only once (aside from inlining). I agree that templates can be a 
helpful feature of C++, and that they can also be abused to cause terrible 
compilation times. I have seen 1/2 hour compilation for a fairly small amount 
of code using Boost.Python and Boost.Serialization, and I hope never again to 
work at a company with that little regard for build times. In particular, I 
hope to avoid Scala, and for now also Rust.

I will also say that I see some merit in Go's avoidance of generics. They're 
great for the coder, but they can be annoying to the reader. Different 
organizations may have different goals.

> I'm not a Go programmer, but one obvious advantage I see from reading the 
> docs is that, unlike in Java, one doesn't need to define the types...
> 
> That advantage is not unique to Go. The object system of the OCaml language 
> provides the same ability.

Yes, @bpr, they are similar. The important thing is that you don't need to 
depend on the same interface file, as you would in Java (and C++, unless you 
trick the compiler). For a large project, it's important to be able to compile 
and test your own code without even downloading your dependencies. With a short 
build-time, you can simply rebuild the entire project, so this advantage 
becomes less important. But "coding to the interface" (with dependency 
inversion) is still a very good (and "SOLID") practice that is easier in some 
languages than in others.

So I do appreciate your ideas, @Krux02, and I will look more closely at your 
macro when I have time.


Re: Go-lang like interface

2016-08-02 Thread bpr
@_tulayang

> I had to say I didn't see any advantage of Go interface.

I'm not a Go programmer, but one obvious advantage I see from reading the docs 
is that, unlike in Java, one doesn't need to define the types (rect and circle 
in the gobyexample example) as implementing a geometry interface, as one would 
have to do in Java.

That advantage is not unique to Go. The object system of the OCaml language 
provides the same ability.

> Side effects exsits in Scheme. You can call set! to change any external 
> variable anytime.

That sounds like an anti-feature to me, kind of like the anti-feature of Python 
(discussed on another thread here) that allows one to add object attributes at 
any time. While I reject the dogma of pure functional programming, I think side 
effects should be localizable. Programming in a _mostly_ side-effect free style 
is a good thing.

That said, I'm happy that Nim has generics, and even if it had some 
interface-like feature, I'd still want generics, just like many Go programmers 
do.


Re: Go-lang like interface

2016-08-02 Thread Krux02
@jester

I am sorry that you have this bad view on this thread. And I am very unhappy 
about the fact that this thread starts this way. Normally I really like to 
explain things, and help when someone does not understand something. I am also 
open to improvements in all directions. Even when the improvement is not a good 
idea I like to talk about what is not good about it. But someones posts _did 
not intend_ to improve on anything.

@bpr Thank you, and yes that is true.


Re: Go-lang like interface

2016-08-02 Thread Krux02
@OderWat

> "This is so bad that several bigger c++ projects completely abandoned 
> templates. " ... is still not backed by even one example. You gave pointers 
> to Templates are very useful but are advanced and should not be overused 
> (google) and I personally don't like templates, but it is fine if you can 
> handle them (C. Muratori). Of course templates make stuff more complex and 
> can harm if you use them wrong or overuse them in general. Thats merely true 
> for everything though as Paracelsus pointed out a long time ago. Then you 
> imply that the reason why c++ templates are "bad" they also "may" make Nims 
> generics bad too. Something which you didn't experienced yourself (yet) and 
> nobody else did afaik.

You are completely right here, and I should change my words in my original 
post. But you should also accept my experience that I had with templates. I 
worked in a project that grew since 2001 I think, and it is based on a lot of 
c++ template programming everywhere. It is a university project where a lot of 
Students work for about a year, and then leave the project again. This inherent 
overuse of templates encouraged the students to adapt the style of template 
programming, and they were used even more. Basically every function and 
datastructure that used a double was templated on the floating point type, 
because maybe one might want to compile it one day with `float`. So basically 
everything was templated. Compilation time exploded, and compilation was only 
possible on the cluster. My computer at home could not build the project I was 
working on at university, because it did not have enough RAM, and the cause was 
the overusage of templates. Since this day my perspective towards templates has 
changed, and I am very careful on the decision wheather I should use templates 
or if it is possible without. And I have not seen anything in the nim 
programming language that promises me that the same thing would happen the same 
way in the Nim world. There are simply no projects in Nim that have grown over 
15 Years.

> At the same time you promote a feature which could be seen much as a "patch" 
> for the missing generics in Go. In fact I remember that I read complaints 
> about Go not having a real generics implementation and have to copy code 
> eventually even with interfaces and delegates at hand.

I do miss generics in Go. It somewhat works to live without them, but it is not 
nice. Just look at the [sorting 
example](https://gobyexample.com/sorting-by-functions) and you know what I 
mean. But I do not think that the interface type in Go is an afterthought to 
patch anything. The whole language is designed around the interface type, and I 
truely thing the go interface is a better solution to polymorphism than the 
vtable at the beginning of a class in languages like c++ C# and Java.

> Then you prove (in my eyes) how ugly and cumbersome it is in the "black box 
> cast ptr macros" implementation you gave, while later you discard a real 
> elegant "see everything" functional approach to the problem as "cheating".

I am sorry I don't understand than sentence. I don't think functional 
programming is cheating or bad. I really like and encourage functional 
programming. But it misses the point in what I tried to show.

> You write: "I just don't like implicit conversions, I think they are scary, 
> because they hide procedure calls from the code reader, and could therefore 
> decrease code maintainability." but isn't this exactly what Go is doing in 
> its implementation?

Yes it is. I will change it to use implicit converters.

> Interfaces may be the best and elegant solution for Go programmers. But I 
> think that I would like to trade them for real generics and templates (which 
> I actually did).

That is completely OK. But maybe you want to be open for an alternative for 
certain use cases.

> EDIT: Using your macros together with a converter to hide the ugly details is 
> cool and may proof being useful.

Thanks a lot.


Re: Go-lang like interface

2016-08-02 Thread jester
Excitement and conviction don't have to be derisive.

This feels like it's tending toward incivility.


Re: Go-lang like interface

2016-08-02 Thread Krux02
> I had to say I didn't see any advantage of Go interface.

Yes, and you are ignorant to learn about them.

> "may not have side effects" ? Really?

Yes, live with it.

> I'm a fans of Scheme language which is a Lisp dialect. I hate Haskell. I hate 
> pure function. I think they are not realistic.

It doesn't matter. 


Re: Go-lang like interface

2016-08-02 Thread _tulayang
@Krux02

> The interface construct in Go works very different from the interface 
> construct in Java

I had to say I didn't see any advantage of Go interface.

> Can you tell me why your foobar in your functional solution has a function as 
> argument, instead of just passing it an int directly?

This is just a demo. proc sort(x: var openarray[int], cmp: (a: int, b: int) -> 
bool) describes more.

> Remember in functional programming functions may not have side effects.

"may not have side effects" ? Really?

I'm a fans of Scheme language which is a Lisp dialect. I hate Haskell. I hate 
pure function. I think they are not realistic.

Side effects exsits in Scheme. You can call set! to change any external 
variable anytime.


Re: Go-lang like interface

2016-08-02 Thread OderWat
@Krux02 "This is so bad that several bigger c++ projects completely abandoned 
templates. " ... is still not backed by even one example.

You gave pointers to _Templates are very useful but are advanced and should not 
be overused_ (google) and _I personally don't like templates, but it is fine if 
you can handle them_ (C. Muratori). Of course templates make stuff more complex 
and can harm if you use them wrong or overuse them in general. Thats merely 
true for everything though as Paracelsus pointed out a long time ago.

Then you imply that the reason why c++ templates are "bad" they also "may" make 
Nims generics bad too. Something which you didn't experienced yourself (yet) 
and nobody else did afaik.

At the same time you promote a feature which could be seen much as a "patch" 
for the missing generics in Go. In fact I remember that I read complaints about 
Go not having a real generics implementation and have to copy code eventually 
even with interfaces and delegates at hand.

Then you prove (in my eyes) how ugly and cumbersome it is in the "black box 
cast ptr macros" implementation you gave, while later you discard a real 
elegant "see everything" functional approach to the problem as "cheating".

You write: "I just don't like implicit conversions, I think they are scary, 
because they hide procedure calls from the code reader, and could therefore 
decrease code maintainability." but isn't this exactly what Go is doing in its 
implementation?

Interfaces may be the best and elegant solution for Go programmers. But I think 
that I would like to trade them for real generics and templates (which I 
actually did).


Re: Go-lang like interface

2016-08-02 Thread Krux02
The interface construct in Go works very different from the interface construct 
in Java. And I did explain the differences. Please don't assume because you 
know how `interface` in java works, you know how `interface` in go works. I 
will add a note in my original post, so further people who read this do not 
make the same wrong assumtion as you did.

Can you tell me why your `foobar` in your functional solution has a function as 
argument, instead of just passing it an `int` directly? Remember in functional 
programming functions may not have side effects.


Re: Go-lang like interface

2016-08-02 Thread _tulayang
@Krux02

I know interface of Java. Go is nothing magical.


Re: Go-lang like interface

2016-08-01 Thread Krux02
@OderWat I was looking for examples online, because I remember that one of the 
c++ talks mentioned that they completely forbid the usage of templates. But I 
can't find that specific talk anymore. I saw too many, and did made a protocol 
about talks I watched. But what I did find is first of all, The google style 
guide which discourages to use [template 
metaprogramming](https://google.github.io/styleguide/cppguide.html#Template_metaprogramming).
 But to be fair, they don't completely ban templates, and I am not sure if they 
distinguish between normal templates as a replacement for generics, or more 
complicated things that rely on template specialization (which is something 
that Nim does not support in its generics for a good reason).

Then I found is the live coding channel [Handmade 
Hero](https://handmadehero.org/) from Casey Muratori. His goal is to write an 
entire game with interesting game engine techniques completely on stream. He 
also says he won't use any third party libraries, he even refuses to use 
operating system abstractions like SDL. I don't know exactly where is says that 
he wouldn't use templates at all, but hiss 3D math library (vectors) with most 
people would implement with c++ templates is completely template free.

Then there is also Jonathan Blow the writer of _Braid_ and _the Witness_. When 
you watch his streams you also realizes that he has a very strong opinion 
againt c++ templates. but again I don't know exactly where in is videos you 
find it, and unlike Handmade Hero I do not have access to his sourcecode.

@_tulayang First of all, do you know the go programming language? 
[Here](https://gobyexample.com/interfaces) is an example of it's interface 
type. Do you understand it? To your _alternative solutions_, it is nice that 
you can prove to be able to program, but when you don't understand the point of 
the original version, and what it is supposed to show, or what its advantages 
are, then your solutions are not helpful at all, because they miss the point.

  * **functional solution**, first of all it's not more functional than my 
solution, just because it uses a lambda expression. But most importantly you 
degraded `foobar` to nothing more than an apply function and copy pasted it's 
logic into each call of foobar.
  * **Another solution**, I see three problems in this line alone: `type 
MyImplementationA = ref object of MyInterface`.

1. MyImplementationA now needs to be a referenced type, no stack allocation 
possible anymore.
2. Usage of MyImplementationA now forces garbage collection, and therefore 
also garbage collection overhead.
3. It uses direct inheritance from the interface type, which is a 
dependency that Go interfaces do not have.



So please ask questions before you write another "solution".


Re: Go-lang like interface

2016-08-01 Thread _tulayang
Another solution:


import future

type
  MyInterface = ref object of RootRef
foo: proc(this: MyInterface): int
bar: proc(this: MyInterface): int

proc foobar(this: MyInterface): int =
  return this.foo(this) + this.bar(this)

type
  MyImplementationA = ref object of MyInterface
  
  MyImplementationB = ref object of MyInterface
m_foo, m_bar: int

proc newMyImplementationA(): MyImplementationA =
  result = new(MyImplementationA)
  result.foo = proc (this: MyInterface): int = 17
  result.bar = proc (this: MyInterface): int = 4

proc newMyImplementationB(m_foo, m_bar: int): MyImplementationB =
  result = new(MyImplementationB)
  result.m_foo = m_foo
  result.m_bar = m_bar
  result.foo = proc (this: MyInterface): int = MyImplementationB(this).m_foo
  result.bar = proc (this: MyInterface): int = MyImplementationB(this).m_bar

var a = newMyImplementationA()
var b = newMyImplementationB(32, 8)

echo foobar(a)
echo foobar(b)



Re: Go-lang like interface

2016-08-01 Thread _tulayang
@Krux02

OK. If you're worried about code bloated, the best way is not to use interface, 
try functional programming (object-oriented programming is inflexible):


import future

type
  MyImplementationA = object
  
  MyImplementationB = object
m_foo,m_bar: int

proc foo(this: MyImplementationA): int =
  return 17

proc bar(this: MyImplementationA): int =
  return 4

proc foo(this: MyImplementationB): int =
  return this.m_foo

proc bar(this: MyImplementationB): int =
  return this.m_bar

proc foobar(f: () -> int): int =
  return f()

var a = MyImplementationA()
var b = MyImplementationB(m_foo: 32, m_bar: 8)

echo foobar(() => a.foo() + a.bar())
echo foobar(() => b.foo() + b.bar())



Re: Go-lang like interface

2016-07-31 Thread OderWat
@Krux02: "Ok, I will search for examples" ... I still wait for them.


Re: Go-lang like interface

2016-07-31 Thread Krux02
@_tulayang It would be nice to know, where you lost my explanation, or where 
you started to skip reading it, because the point was to create a single type 
that can be used to implement `foobar`, and both `MyImplementationA` and 
`MyImplementationB` can be casted to this single type. Of course using generics 
for `foobar` works, too, but that has the disadvantage, that for each type `T` 
foobar is called, a new version of that get's compiled. That's not generally a 
bad thing, but the disadvantage is that in some cases generics, or templates 
(how generics are called in c++) can cause code bloat.


Re: Go-lang like interface

2016-07-31 Thread _tulayang
How about:


type
  MyImplementationA = object
  
  MyImplementationB = object
m_foo,m_bar: int

proc foo(this: MyImplementationA): int =
  return 17

proc bar(this: MyImplementationA): int =
  return 4

proc foo(this: MyImplementationB): int =
  return this.m_foo

proc bar(this: MyImplementationB): int =
  return this.m_bar

proc foobar[T](mi: T): int =
  return mi.foo() + mi.bar()

var a = MyImplementationA()
var b = MyImplementationB(m_foo: 32, m_bar: 8)

echo foobar(a)
echo foobar(b)



Re: Go-lang like interface

2016-07-31 Thread Dippo
+1 Awesome!


Re: Go-lang like interface

2016-07-30 Thread Krux02
@jangko what do you mean with simulated inheritance? In Go you can have an 
[embedded type in a struct](https://golang.org/ref/spec#Struct_types). That 
means your struct has all methods, that the embedded type also has. This is 
effectively pretty much like multiple inheritance. So what simulated 
inheritance is not possible in Go?


Re: Go-lang like interface

2016-07-30 Thread jangko
surprisingly, this Go like interface is very similar with what I have 
implemented when creating high level wrapper for Chromium Embedded Framework in 
[nimCEF](https://github.com/jangko/nimCEF).

in my experience, Nim macro not only capable simulate Go like interface, but 
also interface + simulated inheritance. Indeed Nim's macro can make Nim a very 
powerful language.


Re: Go-lang like interface

2016-07-30 Thread Krux02
@bpr I never said that monomorphization is a harmful language feature. I just 
say that someone needs to be aware of it, and that in some contexts this 
monoporphization is in fact a bad thing.

But in c++ it actually is harmful, because the way c++ deals with templates is, 
to create all required instances **per** compilation unit, and then at link 
time the linker throws all duplicates away. And that I consider as harmful, 
because the same function might get compiled 100 times and then gets thrown 
away 99 times. But the problem here is more on the way how c++ compiles its 
sourcecode, and not on how templates generally work. c++ has the same problem 
with datatypes that are declared in headers. 


Re: Go-lang like interface

2016-07-29 Thread bpr
Rust, by design, also has C++-like monomorphizing templates, so I think it 
isn't fair to imply that templates (i.e., generics implemented by 
monomorphization) are a "considered harmful" language feature these days. As 
Araq points out, D, especially D2, is a template heavy language which mostly 
compiles pretty quickly. 


Re: Go-lang like interface

2016-07-29 Thread Krux02
> Which ones exactly? LLVM, wxWidgets, Urho3D, Ogre, Unreal Engine 4 and even 
> GCC afaik all use templates. We're not in the 80ies anymore where templates 
> where this special bug ridden feature with stupid syntax that nobody 
> understood.

Ok, I will search for examples, and update the post accordingly. I definitively 
heared it in talks about c++. And listing big projects that use templates does 
not beat the argument. Additionally I've heard from Unreal Engine 4 developers, 
that changing the source code has very long builds, even long incremental 
builds maybe because of templates, but that not a prove and not my own 
experience.

> Go's compile times are nothing special at all. Nim sometimes beats Go's 
> compile times, Delphi always beats it, D can beat it and yet D too has 
> extensive templating everywhere...

Ok I did not do the benchmark, but correct would be that Go advertises with 
fast compilation speed. But you are right, in my experience it was not too 
fast. In my code is was always slower than advertised :/. But I can't exclude 
that I did something wrong that cause this increased compilation speed, because 
I never programmed in pure Go, I always had wrappers.


Re: Go-lang like interface

2016-07-29 Thread Araq
Nice work, but please refrain from facts/myths that don't have anything to do 
with your otherwise very nice article.

> This is so bad that several bigger c++ projects completely abandoned 
> templates.

Which ones exactly? LLVM, wxWidgets, Urho3D, Ogre, Unreal Engine 4 and even GCC 
afaik all use templates. We're not in the 80ies anymore where templates where 
this special bug ridden feature with stupid syntax that nobody understood.

> If you remember one of Go's main features is it's compilation speed.

Go's compile times are nothing special at all. Nim sometimes beats Go's compile 
times, Delphi always beats it, D can beat it and yet D too has extensive 
templating everywhere...