It seems Opera's not respecting something with the CSS. The content area not only has a minimum height, but the pre has auto overflows (meaning it should force the box to only a given size and then use scrollbars).
As far as I know a "glyph" has a one-to-one mapping to a character, where "glyph" means the on-screen symbol used to represent the character (not sure whether there exist multi-glyph single characters - although I do think that there are characters which when in some sequence end up being displayed in one glyph, even though they are logically separate characters).
Or do you really mean "octet" or byte, of which several are regularly used to represent a single character during a unicode transmission? In such a case.... define "string". Is a "string" a sequence of bytes, or a sequence of characters?
I believe that e.g. accented characters like é are implemented as a single glyph in fonts, but are composed of two unicode code points: the base character (e) and a modifier character (´).
This is complicated by the issue that unicode also supports the combined character as a seperate single code point, for backwards compatibility with legacy character sets. However the decomposed (normalized) form is the recommended.
> Or do you really mean "octet" or byte, of which several are regularly used to represent a single character during a unicode transmission? In such a case.... define "string". Is a "string" a sequence of bytes, or a sequence of characters?
I know I shouldn't have dipped my ignorant toe into Unicode waters :-)
Maybe a better question would be: If Arc got rid of the character datatype by collapsing strings-and-characters into strings-and-substrings, could you leave "how to represent a string" (chars vs. octets vs. bytes vs. code points vs. glyphs) out of the language spec altogether? Or would such a "clean" string abstraction conflict with having Unicode support (since Unicode is deeply encoding-specific)?
My main objection is the current state of arc.arc : Every iteration construct works with lists or strings, but it won't work well with something that has 'car and 'cdr (they check by using 'acons and 'alist, which use (is (type foo) 'cons) - meaning I had to hack into 'acons and 'alist. For that matter I had to hack into 'isa too)
Generally is-a means "object is this and only this", meaning single inheritance, which was really my meaning. But a scanner isn't a cons (it's a subset of cons; it will fail on scar and scdr). It does has-a 'car and has-a 'cdr.
I think the reason you keep saying has-a is that you're using conses as an example. A cons does has-a car and has-a cdr, but this is too restrictive. For example, say you wanted to make a type that acts like a list, that is, it supports map, each, reduce, all, rev, some, len, nthcdr, and so on.
arc> (= a (my-listtype 'foo nil t 'bar))
(foo nil t bar)
arc> (car a) ; has-a car
foo
arc> (cdr a) ; has-a cdr
(nil t bar)
arc> (map no a) ; has-a map (?!)
(nil t nil nil)
arc> (rev a) ; has-a rev (?!)
(bar t nil foo)
arc> (some no a) ; has-a some (?!)
t
arc> (all no a) ; has-a all (?!)
nil
See what I mean? (Note: I fully agree that it would be really cool if the above actually worked, I'm just arguing that the name has-a makes no sense here.)
has-a scanner interface just means that: it has-a car and has-a cdr. 'map et al. now require an object which has-a scanner interface, and will simply use basic 'car and 'cdr operations to work. This supports genericity: just write 'map et al once, then any new type you create just needs to give 'car and 'cdr, and say it has-a scanner interface, and the existing map will work.
Now suppose we have another type, which has-a 'collide function, which handles the events where it is collided with in the game space. A ship has-a collide function, and the basic collission detection code is something like this:
(thread
(while t
((afn (game-elements)
(iflet (first . rest) game-elements
(each e rest
(when (overlapping first e)
(collide first) (collide e))))
game-elements)))
The above now works on ships. Now suppose we add a new type of game element: a missile. We simply define its 'collide function, and declare it as having that function; now it magically works without changing the collision-detecting code.
The point mostly is that those problems probably stem from is-a semantics. It might be that has-a semantics might work better.
In such a case a has-a semantics means that circle "has-a" function to compute its area, a function to compute its circumference, etc. An ellipse "has-a" function to compute its area, a function to compute its circumference, etc. It doesn't matter whether the user thinks of circles as special cases of ellipses or not.
Perhaps the way to go would be to support interfaces without requiring type checking. Basically you simply say "all I care about is that this object can be passed to that function".
That said a semiformal way of expressing this - probably by giving a name to an interface (which is just a set of function symbols that an object supports) - might be useful. This way wouldn't necessarily be checked by the program - it might be useful to have it be read by the programmers as part of the code/documentation.
(typeclass 'scanner 'car 'cdr)
; programmer reads: a scanner is anything that somehow supports 'car and 'cdr
(def foo (a)
" A ridiculously complex library function which does
a lot of useful things and which the library user
probably doesn't want to read in full, because he or
she is using the library so that he or she doesn't
have to think about it.
See also [[bar]] "
(must-have a 'scanner)
; programmer reads:
; "Anything I define which supports 'car and
; 'cdr can work on this function"
(ridiculously-complex-expression-involving a))
OK, maybe I flipped out a bit when I heard the word 'type' mentioned. It brought up nightmares of using Java and C++ and so forth.
The kind of thing you're suggesting here does look powerful (and most importantly, optional!) If you combine it with sacado's suggestion for putting the methods in the tag, then you have a very powerful type system indeed.
I just have one contentious thing left to say: when you move away from is-a typing to has-a typing, does it really make sense to use the word 'type' at all? Aren't we really talking about what your functions can do, rather that what your objects are? For example, if you define car and cdr to work on strings, have you added strings to a new sequence type or have you expanded the power of your functions? I prefer to think that you've done the latter, and save the word 'type' for the basic is-a types that every language has to have.
It's the word 'type' I'm objecting to now, not the general idea. Perhaps we need to get out of the typing mindset in order to really break new ground.
The value of types is the name you associate with an object. Instead of giving a really long list of "functions that should work on the object" you say "an object of this type". So instead of saying "an object that has 'car and 'cdr" you just say "scanner".
How about co-opting bits of Haskell type system.... Hmm.
Basically 'num here would be a specific "is-a" type, not necessarily the "has-a" type I was thinking. But it should be doable. Basically you just need to redefine 'defm to put stuff in a table as well as into the symbol, and have type-declaration scan through the code for stuff in the table that's declared with specific types.
But we need to figure out first how to handle types: "is-a" or "has-a". Does 'defm dispatch off a "is-a" relationship or "has-a" relationship? Possibly as in Haskell, with a "is-a" type having "has-a" set of interfaces/typeclasses/baseclasses.
Oh please no! Static typing and Lisp - especially a Lisp like Arc that puts even more emphasis on being as dynamic as possible - don't mix. If we want performance improvements like this, that's what type annotations are for. Those work fine in CL for gaining performance, and integrate well into dynamic languages.
If we add Haskell's type system, we'll just end up with an ad hoc, informally-specified, bug-ridden, slow implementation of half of Haskell. That's not what anyone wants.
Err. The idea is that these are the "type annotations" you are looking for. I never said anything about making this mandatory; it's merely the implementation layer for type annotations.
I wonder if some of the work in optimizing Self, such as polymorphic inline caches [1] might be applicable for non-object oriented dynamically-typed languages such as Arc.
The funny thing is that I wrote FFI for one reason besides optimization : I wanted a POSIX interface, so as not to rely on the system function, which is as broken as any shell script.
Imagine you make a script to remove all files ending with a ~ as they are backup files : foo.tex~, bar.c~ and so on. Now imagine your stupid user named a file ~. Guess what happens if you call "rm -r $file" in your script. It also works with files starting with - and many other funny things.