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

A macro for algebraic data types (ADTs) #58

Open
glyh opened this issue Jan 25, 2023 · 3 comments
Open

A macro for algebraic data types (ADTs) #58

glyh opened this issue Jan 25, 2023 · 3 comments
Labels
feature New feature or request

Comments

@glyh
Copy link

glyh commented Jan 25, 2023

I just stumble across ADT in python, and it translate into this in hy. Which is kinda ugly.

Here I present a macro, so it's looks a bit better:

macro implementation
(defmacro defadt [name #* constructors]
  (let [alts []]
    `(do
       (import 
         __future__  [annotations]
         dataclasses [dataclass])
       ~@(lfor alt constructors 
            (if (= (type alt) hy.models.List)
              (let [[name #* fields] alt
                    fids (list (map 
                                (fn [id] (hy.models.Symbol f"arg{(+ id 1)}"))
                                (range (len fields))))]
                (alts.append name)
                `(defclass [dataclass] ~name []
                   ~@(lfor [f-id f-type] (list (zip fids fields))
                      `(annotate ~f-id ~f-type))
                   (defn __str__ [self]
                     (+ ~f"({name}" 
                        ~@(list 
                            (map (fn [fid] `(+ " " (str (getattr self ~(str fid))))) 
                                 fids)) 
                        ")"))))
              (do 
                (alts.append alt)
                `(defclass [dataclass] ~alt []
                   (defn __str__ [_]
                     ~f"({alt})")))))
       (setv ~name (| ~@alts)))))

(defadt Shape 
  [Point float float]
  [Circle float float float]
  [Rectangle float float float])

(Circle 3 4 5)

(defadt Tree
  Dead
  [Leaf int]
  [Branch Tree Tree])

(Branch
  (Branch (Leaf 1) (Leaf 2))
  (Branch (Dead) (Branch (Dead) (Dead))))

But noted that not all properties is supported, because in my perspective we should keep adt simple.

@glyh
Copy link
Author

glyh commented Jan 25, 2023

I don't know if there's a better syntax though, feel free to discuss, :)

One potential, conforming to hy's type annotation.

(defadt Shape
 [Point     #^float x
                    [y 0]]
 [Circle    #^float x
            #^float y
            #^float r]
 [Rectangle #^float x
                    y
            #^float w
            #^float h]
 [Whatever x y z a])

@Kodiologist
Copy link
Member

Kodiologist commented Jan 25, 2023

Please don't use the issues list as a stream-of-consciousness. Think through what you want to say, experimenting as necessary, and then say it.

(I wrote this comment in reply to a lot of other comments that are now deleted.)

@glyh
Copy link
Author

glyh commented Jan 25, 2023

Well, I don't know what exactly should this macro look like because in genral lisps' don't have ADT. Therefore I don't know what the syntax should look like. I post the last one to ask people's opinion on it.

They do look a bit noisy, I'm going to clean it up a bit. Sorry about that.

EDIT: And potentially something here should be send to hy as an issue since I'm not sure if macros in hy is working properly again.

@Kodiologist Kodiologist added the feature New feature or request label Jan 26, 2023
@Kodiologist Kodiologist changed the title A macro for ADT A macro for algebraic data types (ADTs) Jan 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants