Arc Forumnew | comments | leaders | submitlogin
1 point by aw 5187 days ago | link | parent

Using extend or defrule with a test for type seems like a common pattern... perhaps we should extract that into its own macro.


1 point by rocketnia 5187 days ago | link

Pauan and I were talking about something like that at https://convore.com/arc-runtime-project/getting-critical-cha..., but it was specific to defcall. I wonder if the idea of a type-table case could make sense for lots of operations.

In Lathe/arc, I filter on the first argument's type using "ontype" or multiple first arguments' types using "ontypes":

  (use-fromwds-as rc (+ lathe-dir* "orc/orc.arc"))
  (= my (nspace))
  
  ; These are already defined in orc.arc, but I'm redefining them here
  ; for the sake of example.
  
  (rc:ontypes rc.oiso2 (a b) (cons cons) my.cons
    (and (rc.oiso2 car.a car.b) (rc.oiso2 cdr.a cdr.b)))
  
  (rc:ontype rc.otestify () fn my.fn
    self)
  
  ; General pattern:
  ;
  ; (rc:ontypes <rulebook> <parameters>
  ;     (<type of a leading parameter> ...) <rule label (optional)>
  ;   <implementation>)
  ;
  ; (rc:ontype <rulebook> <parameters other than the first>
  ;     <type of the first parameter> <rule label (optional)>
  ;   <implementation, where "self" is the first parameter>)
https://github.com/rocketnia/lathe/blob/master/arc/orc/orc.a...

In orc.arc, this comes with an inheritance system I don't use much, but I've found I use 'ontype itself a lot when defining new types. Porting the inheritance system would be hard without porting Lathe's rule precedence system along with it.

In lathe.js, I recently tried adding lathe.instanceofRule( ... ), which defines rules that check the type of their first argument. This was largely a failure, as it clutters up the signature line so much that I end up spreading it over three lines of code, when often I could have had a one-line signature and a one-line explicit check. I haven't given up on it completely, though, since it decreases my token count slightly. :-p

-----

1 point by akkartik 5187 days ago | link

Do you mean like defgeneric?

Update: I've been mulling adding 'def :type' to wart for some time, so that I can say (def prn(x) :type 'integer ..) rather than (def prn(x) :case (isa x 'integer) ..).:

  (extend-macro def(name params &body body) :case (iso :type (car body))
    `(def ,name ,params :case (isa ,(car params) ,(cadr body))
       ,@(cddr body)))
But I often want to dispatch on different args. I'm not sure the first or last arg are sufficiently common to merit a shortcut.

-----

1 point by Pauan 5187 days ago | link

In my experience, it's usually the first argument, so I think having a :type would be useful, and in the cases where it isn't, you could fall back to :case (isa ...)

But of course, that's up to you.

-----

2 points by akkartik 5176 days ago | link

Yeah after holding off for a week I decided it would be useful.

https://github.com/akkartik/wart/commit/9559f27eec3994d9779b...

Update 2 hours later: Turns out if isa can handle a list of types, so can :type.

https://github.com/akkartik/wart/commit/1a8400dfebb16bd154da...

-----