Arc Forumnew | comments | leaders | submitlogin
3 points by almkglor 3993 days ago | link | parent

Arc-f actually has clojure-style multimethods hidden somewhere (I invite you all to search for them!). However, there are very deep reasons why I did not encourage their use.

The most important is that the dispatcher function is a limiting factor. To be specific, the dispatcher function means that extending the function is limited to what the dispatcher expects.

If the dispatcher function expects exactly one argument, you cannot create a method with an optional argument. For instance, consider a shape rectangular-prism

  (= shape
     (obj shape 'rectangular-prism
          height 2
          width 3
          depth 4))

  (method area 'rectangular-prism (p (o face 'front))
    (case face
      front  (* p!width p!height)
      back   (* p!width p!height)
      left   (* p!height p!depth)
      right  (* p!height p!depth)
      top    (* p!width p!depth)
      bottom (* p!width p!depth)))
Unfortunately, because the dispatcher for 'area expects exactly one argument, you cannot extend 'area with a method that supports optional arguments.

I'll be putting up a more extensive rationale for why I decided not to use Clojure-style multimethods in Arc-F (despite already having implemented them), and would very much rather prefer to bash my head trying to implement CLOS-style multimethods.



4 points by rntz 3992 days ago | link

It's true that if the dispatcher expects exactly one argument, you can't add optional arguments. The solution is very simple: don't make dispatchers which expect exactly n arguments. Make all your dispatchers take rest parameters which they ignore. In fact, 'multi-keyed already does exactly that, so if you used (multi-keyed area 'shape), your example would work exactly as expected. It's not a hard fix.

Regarding reasons for not implementing Clojure-style multimethods in Arc-F, how about this one: because you can implement them in plain old arc! Don't put stuff in Arc-F if it can be done in Arc or Anarki already. Interoperability is good - we don't need to fork the community as well as the language.

-----

1 point by almkglor 3992 days ago | link

> It's true that if the dispatcher expects...

It's not just the number of arguments. One advantage of CLOS-style multimethods is this:

  (def bam (a b)
    (err "collision type unknown!"))
  (defm bam ((t a ship) b)
    (destroy ship)
    (destroy b))
  (defm bam ((t a ship) (t b missile))
    (destroy ship)
    (destroy missile)
    (add-points missile!source))
Because of the computation of keys, you can't exactly implement the above using clojure-style multimethods without tricks like method bouncing.

Like I said: already implemented clojure-style multimethods. And tried it. So yes: I'll continue bashing my head implementing CLOS-style multimethods, because while clojure-style multimethods are cute, they're not good enough for all cases. Arguably neither are CLOS-style multimethods, but at least we have an alternative choice.

Edit:

Also, there's a good reason for implementing this in the scheme-side: efficiency. Your implementation of clojure-multimethods allocates a cons cell for each argument to the multimethod. The scheme-side implementation does not, because on the scheme-side I have access to the ar-funcall* functions.

Efficiency of course is not a concern, except when it is.

As an aside, there are several bits of Arc-F that look like they're implemented in Arc, but are actually implemented in the scheme-side. There's an Arc implementation of them in arc.arc, which is labeled as "IDEAL", while the actual binding to the scheme side is labeled as "REAL". For example, the basic compose function is actually implemented in the scheme-side, but there's a reference Arc implementation in arc.arc marked "IDEAL". The only reason they're on the scheme-side is due to efficiency. Ideally, they would be in Arc: realistically, they are better implemented in the base system.

-----

1 point by rntz 3992 days ago | link

This is true, and indeed I mentioned it in the OP; you can't do type-based dispatch with clojure-style multimethods except on exact matches. You also can't get method chaining. But clojure-style has the advantage of being damn simple, and easily permits dispatch based on non-type-based conditions. CLOS style has the advantage of being more flexible about dispatch and integrating well with OO methodologies.

I'm not trying to convince you that CLOS multimethods are bad or not to implement them; a full implementation for Arc or Arc-F would be _very cool_. CLOS is without a doubt my favorite thing about Common Lisp. But Clojure-style multimethods are not "cute" or useless. They're just not a universal panacea. Very little is.

-----

1 point by almkglor 3992 days ago | link

> "cute"

For me, cute means something really really nice, not necessarily useless. Like cute mature women, for example. Or better: cute girls, with guns. LOL.

Method chaining may require us to rethink PG's type system, at least if we want to handle a drop-down to a more generic type (which arguably is the more interesting bit about chaining). It's reasonably easy to drop from the "argument 2 matched type T" to "argument 2 matched no types", but how about when we want to drop from "argument 2 matched derived type D" to "argument 2 matched base type B"?

Waa.

We would have to have an operator which determines if D is derived from some random type B, and forcibly standardizing on it. This is going to make my head explode.

-----