Arc Forumnew | comments | leaders | submit | almkglor's commentslogin

Hmm. Mockup of how it would be used.

  ; In arc.arc, or maybe something equivalent in
  ; ac.scm.
  (typeclass 'cons 'car 'cdr 'scar 'scdr 'apply)

  ; In our library, where we can't (or at least,
  ; "shouldn't") redefine the built-in Arc 'cons
  ; typeclass.
  ; A perfect subset of 'cons.  
  (typeclass 'scanner 'car 'cdr)

  ; Dumps out a character scanner or list
  ; to a port
  (def dump-out (port l)
    ; Note: we expect has-a to return t
    ; even if l is a 'cons - i.e. the type
    ; system should be smart enough to
    ; realize that 'cons provides all the
    ; interfaces of 'scanner.  Prolly something
    ; like:
    ; (= all-functions (mappend [instance-functions-of _] (type-classes-of ob)))
    ; (all
    ;   [some _ all-functions]
    ;   (instance-functions-of requested-type-class))
    ; above can be optimized by using tables - put all
    ; of the requested type class's instance functions
    ; in the table, then remove everything that exists in
    ; all-functions; if we finish all-functions while
    ; table entries exist, we know the object doesn't
    ; have that type class
    (unless (has-a l 'scanner)
      (err "Not a scanner"))
    (map [write _ port] l))

-----

5 points by nex3 6464 days ago | link

Now, the thing I like about implicit has-a relationships is that they guarantee less code than making it explicit, in that they're the same amount of code sans type declarations and checks. For example, the above would be simply

  (def dump-out (port l)
    (map [wrie _ port] l))
No typeclass declarations and no type checking. This also has the advantage of being identical to the code you'd write if you were completely unaware of a scanner abstraction.

Also, on a more philosophical level, I feel like type checking is just out of place in a dynamically-typed language like Arc.

-----

4 points by almkglor 6464 days ago | link

Not really my point. The point is that the trivial check:

  (unless (has-a a 'scanner)
    (err "type error"))
May be closed into a macro:

  (mac type-declaration (a typ)
    `(unless (has-a ,a ,typ)
       (err "type error")))
...which ends up being the optimizing compiler's clue:

  (def dump-out (port l)
    ; a completely optional declaration
    ; for:
    ; (1) an non-optimizing interpreter, so that
    ; you have some chance of checking errors, and
    ; (2) the optimizing compiler, so that it can
    ; do some shortcuts.
    (type-declaration l 'scanner)
    (map [write _ port] l))
^^

You can then trivially redefine type-declaration as:

  (= type-declaration
     (annotate 'mac nilfn))
To disable type-checking.

Oh and yeah: type checking is plenty in-place, if you're building a library. If the library's interface functions simply passed the object to library-internal code without checking, the error will pop up as coming from some code deep in your library, where your user might be less inclined to trace (because it might be your bug, not theirs). At least if you do the check on the interface functions themselves you have proof that the bug is in the user's code.

I agree it's out-of-place in most apps of course.

-----

4 points by nex3 6463 days ago | link

But that macro, and the whole plumbing behind declaring and checking type classes, just don't have to exist if you make it implicit. It's a lot of added complexity for no gain in power. All you gain is a little type safety - and if you need type safety, Arc (and Lisp in general) is not your language.

I wonder how much type-checking major Lisp libraries really do have. In the dynamically-typed-language libraries I've looked at, there are more or less no type checks. In the Ruby community, they're specifically discouraged, because they limit the power of duck typing.

-----

3 points by almkglor 6463 days ago | link

Yes, but who says it has to be used? In the majority of code, there won't be type checking, but we do want to say something like this:

  This function accepts a list of ordinal types
which we can simply put in-code as:

  (type-declaration a 'Scanner)
  (type-declaration (car a) 'Ordinal)
The point is that the function doesn't specifically accept a list of strings or numbers - it accepts a traversable sequence of anything that can be ordered. The type-declaration thing is just a notation to express that to someone else.

-----


[1] This is about correct; Haskell dispatches off the is-a ness of the type. However, code you write will generally ask for the has-a relationship:

  {- merge used for mergesort -}
  merge :: Ord a => [a] -> [a] -> [a]
  {- The "Ord a" above asserts that the type "a"
     should be an "Ord"inal, i.e. it should support
     < <= > >= == methods
  -}
  merge [] [] = []
  merge a []  = a
  merge [] b  = b
  merge a:as b:bs
        | a < b     = a:(merge as b:bs)
        | Otherwise = b:(merge a:as bs)
  {- Of course, I haven't programmed Haskell in a while,
     so the above code might be wrong. -}
If we had has-a relationships, we might say something like this in Arc:

  (def merge (a b)
    (unless (and (has-a (car a) 'Ord)
                 (has-a (car b) 'Ord)
                 (is (type a) (type b)) )
      (err "Type error, needs Ord"))
    (if
      (no a)
        b
      (no b)
        a
      ; now we're assured < works
      (< (car a) (car b))
        (cons (car a) (merge (cdr a) b))
        (cons (car b) (merge a (cdr b))) ))
Hmm. LOL. I can just imagine a macro to do that type checking for you:

  (type-check (list a b)
     (Ord a) ((a . as) (a . as)))
It's beginning to look lot like Haskell ^^. Heck. arc.arc is congruous to Haskell.Prelude

-----

4 points by nex3 6464 days ago | link

Yeah, I've seen several ways to express has-a relationships. Statically typed languages like Haskell tend to express them as is-a relationships (e.g. Int is-a Ord), since that meshes well with type safety. Languages that embrace duck typing, like Ruby, tend to make has-a relationships implicit; just use the method (or in Arc's case, function) and assume that the receiver will react properly. This meshes well with the late-binding, screw-static-verification philosophies of these languages, which Arc generally shares, and the message-passing object model, which Arc does not.

This is where I assume Arc will end up building its type system, if it ever does embrace a single type philosophy[1]. Even if it doesn't have a message-passing model, its dynamism makes the implicit has-a model a good fit.

The only language I've seen that embraces explicit checks for has-a relationships, as opposed to expressing them as is-a or making them implicit, is Javascript. This is mostly because you're dealing with objects that have an inherently variable and ill-defined interface that you don't know a lot about at compile-time. I think most JS developers view it as an annoying necessity, though, so I'm inclined to believe it's the least pleasant way of dealing with has-a (despite being the most explicit).

[1] Speaking of which, I really think it should. This is sort of implicit in taking part in all these discussions about typing, I suppose, but I wanted to mention it anyway. Any sufficiently powerful, has-a-based type system won't be a constraint on the language, but will rather allow powerful abstractions like Ruby's #each and almkglor's scanner.

-----


"Abstract Base Class" also happens to be the term preferred in C++ for Haskell's "type class" and Java's "interface". So it probably is-a python abstract base class ^^.

That said the problem with using a "base" class with an inheritance model is that it's deucedly difficult to think in terms of multiple inheritance (multiple inheritance is so hard most languages don't use it). Mix-ins help ameliorate this by being a has-a relationship.

-----

1 point by almkglor 6464 days ago | link | parent | on: Predicates: `is...' versus `...?'

Interesting. Care to start hacking the arc-wiki docstrings? I know I haven't even completed the "see also" links ^^

-----

1 point by almkglor 6464 days ago | link | parent | on: Predicates: `is...' versus `...?'

Perversely, I like CL's versoin. foop, foo-p ^^

Note however that Arc's naming conventions are even more haphazard:

http://arclanguage.org/item?id=3604

-----

3 points by almkglor 6464 days ago | link | parent | on: hosting for arc web app

(quit) shuts down gracefully AFAIK. If you're not confident of it, use (= quitsrv* t) and make one request from the server.

-----

3 points by almkglor 6464 days ago | link | parent | on: Will Arc ever be as fast as CL?

Dang.

Personally I don't even use infix. If the slowdown comes from that...

-----

2 points by eds 6464 days ago | link

Yeah, sorry about that. I wasn't thinking about performance when I originally put infix.arc up on Anarki, and since I was doing a lot of testing at the time I found it convenient to add it to libs.arc. Perhaps it would be best to leave it out by default though.

-----

2 points by eds 6464 days ago | link

Done. You shouldn't get any more performance hits from infix math unless you explicitly load infix.arc.

-----

4 points by almkglor 6465 days ago | link | parent | on: Poll: Where are you from ?

Lazy, lazy!

-----


Created a better scanner syntax, based on my idea here:

http://arclanguage.org/item?id=4785

On the git. ^^ It's also somewhat optimizing: the representation is mutated if 'car/'cdr is invoked on the scanner, and the function that captures the expression's environment is replaced with a function which returns the expression's result. Of course, I made sure not to actually measure any so-called improvement in time. ^^

-----

3 points by almkglor 6465 days ago | link | parent | on: Poll: Where are you from ?

Philippines. Lousy country. Anyone want to get me out of here?

-----

1 point by almkglor 6464 days ago | link

Hmm, looks like at least one other guy is from the Philippines too. Sino ka?!? Magpakita ka nga!!

-----

1 point by dido 6463 days ago | link

Sino yung pangatlo?

-----

1 point by almkglor 6463 days ago | link

Hmm! Tatlo nga! Baka nagkamali lang ng pindot?

(translation, in case it's just someone who clicked the wrong country: dido: Who's the third? almkglor: Hmm! It is three! Maybe someone just clicked wrong?)

-----

1 point by dido 6463 days ago | link

Where would you go? Kahit saan ka naman pumunta marami pa ring kalokohan. :p

-----

1 point by almkglor 6463 days ago | link

Hehe sa bagay maraming pinoy eh ^^

-----

More