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

Macro to generate variant objects #5

Open
andreaferretti opened this issue Sep 26, 2018 · 10 comments
Open

Macro to generate variant objects #5

andreaferretti opened this issue Sep 26, 2018 · 10 comments

Comments

@andreaferretti
Copy link

First, kudos for your new library!

As you probably know, patty consists of two macros: one to generate algebraic data types and the other one to do the actual pattern matching. Since you have generalized a lot the pattern matching capabilities of patty, I would like to deprecate it in favour of gara. Is there any chance that the other functionality may be included here in some form? Otherwise it would remain orphan.

@alehander92
Copy link
Owner

Hey, thank you!

I'd be sad to see patty deprecated, but I'd be very happy to welcome you as a contributor. My goal was to create the initial several version(s) but if other people have serious interest in co-developing/maintaining it to move the repo to an organization (making it a community effort), but of course that's if you or other people have time/interest in that.

I actually thought about the ADT problem these days.

Gara actually includes a ~ macro: it works like ~TypeName.discName(field: value,) and it should also get a ~TypeName.discName(list of values) form.
e.g.

let a = ~Commit.Normal(name: "A", diff: "b")
let b = ~Commit.Normal("A", "b")

I wondered if I can somehow add to the compiler a compile time helper which can do something like discriminatorUsages(enumKind) returning all types using an enum as a discrimantor. This would be very helpful, as then for types which are used once(most of the enum discriminators)
we can have

let a = ~Normal(name: "A", diff: "b")
let b = ~Normal("A", "b")

Of course ~ is an example, we can have a different name for that.

Now, why? I love patty's variant(ADT) syntax but the problem is that a lot of nim code already defines variants with object definition. I wanted to still have something that makes all those existing variants easier to use. (Another option would be to just have variant ExistingType which generates boilerplate: e.g. default $, == functions). Such a constructor syntax can still be compatible with the ADT-s generated by a macro: I can see how it might be unappealing, but I am afraid for all the existing ADT-s it would be hard to get further.

Now, about the definition of new ADT: I wondered if there is a way to add your macro to type sections. (I even opened an issue once in patty before I knew well how macros work :D )

I doubt that Araq will want a new builtin variant keyword which does the same, but maybe we can get
typeSectionMacros similar to forLoopMacros which lets one add content both to the type sections and after their end. e.g.

macro variant*(definition: untyped): untyped {.typeSection.} = 
  # I want to generate a (NimNode, NimNode): one for the type section and one for the code section
  ..

and be used like

type
  A* = variant #usually with : but Araq said we might be able to have macro invocations without colon
    commonField: Type
    Circle(..)
    Square(..)

Of course even if we can't have a typeSection macro, we should definitely include the current variant macro then.

@andreaferretti
Copy link
Author

No need to be sad for patty, your solution is 1000 times more complete! :-)

In the last year I was not able to work much on Nim projects, save for keeping them up to date with latest Nim. If/when I find time, I would be happy to contribute, though!

I don't like especially the syntax to declare algebraic data types in patty (variant / variantp), it's just the first thing that worked. That said, I think that ~ is nice but a little limited. I actually like your other proposal: having a way to generate equality, pretty printing etc. for existing variant types.

@alehander92
Copy link
Owner

Well, I mostly followed your patty todo list, honestly I guess that could be probably added to patty, but it just seemed easier for me to start from scratch.(not a good thing in general :D).

What do you find is ilimited with ~ ?

Yeah, I'll think about it, I actually think stuff like this might be easier to directly be added to the stdlib than the pattern matching

@andreaferretti
Copy link
Author

About ~: I was just saying that using a macro like this instead of generating constructor functions works, but there are other things that one may want to generate (==, $, copy constructors...) which are not covered by this macro. This is why I liked your other proposal to generate equality, pretty printing etc. for existing variant types.

@andreaferretti
Copy link
Author

Also, a limitation of the ~ macro is that it does not work in all contexts (unlike simple functions), for instance this does not compile

import gara

type
  ShapeKind = enum Rectangle, Circle
  Shape = object
    case kind: ShapeKind
    of Rectangle:
      w, h: float
    of Circle:
      cx, cy, r: float

echo(~Shape.Rectangle(w: 1, h: 2).w)

@alehander92
Copy link
Owner

alehander92 commented Sep 29, 2018

Yeah, in this case something like init might be better

Shape.Rectangle(w: 1, h: 2).init.w

Still, I think that's a non-issue actually, because how often would you create a variant to immediately access a field / method on it and throw it away in the process?

@alehander92
Copy link
Owner

for now a RFC in https://github.com/nim-lang/Nim/issues/9139

@alehander92
Copy link
Owner

@andreaferretti after some discussions with Araq, I have a plan for supporting shared names with your macro: I'll try to port it to gara these days. (but maybe also submit a PR to patty)

@alehander92
Copy link
Owner

ok, i have to remember what i meant, i remember something about generating if-s for subcases and that one can generate if <condition> .. stuff and expect that this would be often optimized out..i can search in irc

@akavel
Copy link

akavel commented Apr 3, 2020

The newly released Nim version 1.2 seems to introduce support for macro pragmas in type sections; I don't have a clear idea yet how exactly this could be used for patty or gara, but I wonder if it could make something possible here? ^v^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants