;; arc syntax
;; see http://www.paulgraham.com/arc.html
(require 'stdlib)
(define fn lambda)
(define pr princ)
;; rfn (a macro) instead of labels.
;; (rfn len (x) (if (no x) 0 (+ 1 (len (cdr x)))))
;; macro to make + polymorphic:
;; (+ "aap" "noot") => "aapnoot"
;; alternate read-syntax for fn's:
;; [+ _ 1] for (fn (x) (+ x 1))
;; CL: (cond ((a x) (princ "!") (b x)) ((c x) (d x)) (t (e x)))
;; Arc: (cond (a x) (do (pr "!") (b x)) (c x) (d x) (e x))
;; Usually use if, which binds it: (if (a x) (car it))
;; = is setf (no set or setq), and hence assignment.
;; Can create local vars by assignment.
;; (do (= x 5) (cons x 'a)) => (5 . A)
;; Any sequence of code is a block.
;; Macros separate 1st class objs.
;; (macro (test . body) `(if ,test (do ,.body)))
;; binding: with like CL let:
;; (with (x 'a y 'b) (list x y)) => (A B)
;; let for single variable case:
;; (let x 'a (cons x 5)) => (A . 5)
;; Arc's 4 basic iterators:
;; (for (= i 0) (< i 10) (++ i) (pr i)) => 0123456789 NIL
;; (to i 10 (pr i)) => 0123456789 NIL
;; (each x '(a b c) (pr x)) => ABC NIL
;; (let i 0 (while (< (++ i) 10) (pr i))) => 123456789 NIL
;; while captures it:
;; (while (read) (pr it))
;; All capture keep and sum:
;; (each x '("al" "bob" "joe")
;; (if (> (len x) 2) (keep x))) => ("bob" "joe")
;; (to x 5 (sum x) (pr x)) => 01234 10
;; Compounds = Functions on Indices
;; Any compound data object (meaning one with several separately
;; addressable parts) behaves like a function on indices. So for
;; example to get the third element of a list you "call" the list with
;; 2 as an argument. This makes programs shorter and saves us having
;; separate access functions for each data type.
;; ("hello" 2) => \l
;; (map "carpet" '(3 4 1 2)) => (\p \e \a \r)
;; CL: (aref a 5)
;; C: a[5]
;; Arc: (a 5)
;; Classes and Objects, Single inheritance (may change)
;; (= pt (class nil 'x 0 'y 0))
;; (type pt (x 0) (y 0))
;; (= p1 (new pt))
;; (p1 'x) => 0
;; (++ (p1 'x)) => 1
;; Strings Work Like Lists
;; (car "abc") => \a
;; (cons \a "bc") => "abc"
;; Parameter Lists
;; Parms are symbols or (opt | get | ds ...)
;; (def foo (x (ds (i j)) (get m n) (opt q 'a) . z)
;; => (list x i j m n q z))
;; (foo 1 '(red green) (db m 'a n 'b) 'hel 'lo)
;; => (1 RED GREEN A B HEL (LO))
;; (let (ds (x y)) '(a b) (list x y)) => (A B)
;; Arc allows three things in parameter lists besides ordinary
;; symbols: (opt var default) which indicates an optional parameter
;; whose value defaults to default; (ds pattern) which matches a
;; pattern of variables against an incoming list, like Common Lisp
;; destructuring-bind; and (get vars) which picks one or more
;; variables out of an incoming db or instance with corresponding
;; keys.
;; ======================================================================
;; We've had so many suggestions for Arc features that I thought
;; I'd better collect them all. So far I have barely skimmed most
;; of these, but there are clearly some interesting ideas here,
;; so I thought I should put them online so that everyone can see
;; them. --pg
;;
;;
;; *** Dorai Sitaram: Recursion
;;
;; fn-named could be renamed rfn or fnr, r for
;; recursive. This gets rid of your one hyphenated name.
;;
;; You can then have, a la Scheme's named let, the
;; form rlet. In the following, == notates "is syntax
;; for".
;;
;;
;; (rlet NAME VAR INIT BODY ...)
;;
;; == (let NAME (rfn VAR BODY ...)
;; (NAME INIT))
;;
;; Of course you need rwith too.
;;
;; (rwith NAME (VAR0 INIT0 ...) BODY ...)
;;
;; == (let NAME (rfn NAME (VAR0 ...) BODY ...)
;; (NAME INIT0 ...))
;;
;; Of course you want tail-call elimination, and since you
;; can use tail recursion to iterate, you can remove your
;; four looping operators. I think this mayhem is OK,
;; because I have never thought of tail-recursive
;; loops as a poor human's substitute for "real" loops.
;; If you really must have the latter, you have macros
;; anyway.
;;
;;
;;
;; *** Greg Sullivan: Keep, Sum, Syntaxes
;;
;; Re the "keep" and "sum" operations, it seems like you could have
;; those take an optional function argument that would apply arbitrary
;; computation to the arguments, with the defaults being
;;
;; (fn x . (add! x them))
;;
;; and
;;
;; (fn x (set! total (+ x total)))
;;
;; or something. Seems like you're aiming for more usable versions of
;; map and fold.
;;
;; More off the deep end is: what about optional front-end syntaxes?
;; Much as we all know that syntax really shouldn't matter, it seems to.
;; We all know that S-expressions are just a syntactic and direct
;; representation of the syntax tree -- could we have parsers from infix
;; syntax to S-expressions? I suppose the hard issue -- maybe the only
;; hard issue -- is macros. But I think we could solve it.
;;
;;
;;
;; *** Alan Bawden: First-class Macros
;;
;; During your presentation at LL1 last Saturday you mentioned that you were
;; considering macros that were first-class values. Many people in the
;; audience seemed to think that this was clearly an absurd idea -- I think
;; you even wavered about this yourself at one point. Well, don't give up on
;; this idea until you have read my paper about how first-class macros can be
;; a sensible notion. See .
;;
;; The executive summary is that you can can have first-class macros and still
;; do all macro-expansion at compile time, at the cost of some (quite minimal)
;; "type" declarations. Unfortunately for you and your current project, I
;; wrote that paper with the statically typed programming language audience in
;; mind (ML, Java or even C). I do mention in passing that the idea would
;; also work for a dynamic programming language (Scheme or Dylan), but I don't
;; explain how in detail -- so you'll have to extrapolate a little.
;;
;; I think the idea is quite cool, and, as I show in the paper, it has some
;; very interesting applications. (For example, it's almost all you need to
;; construct a complete a module system.)
;;
;;
;;
;; *** Ken Anderson: (get)?
;;
;; Some questions:
;;
;; Q1: How do i write a function that takes two arguments that i want to get
;; the x and y fields of?
;;
;; (def area ((get x y) (get x y)) ???)
;;
;; They could be labeled by argument position so i could say:
;;
;; (def area ((get x y) (get x y))
;; (abs (* (- x2 x1) (- y2 y1))))
;;
;; Q2: If there is a get argument, (get x y), how can i access the underlying
;; object itself?
;;
;; I think it is interesting to try to provide desctructuring information in the
;; function defnition. However, Haskell does this, for example, by allowing
;; multiple definitions of the function.
;;
;; While i like some kind of pattern matching in function definition, i'm not
;; sure it should be part of the core language.
;;
;; For the core i'd like to just see what Scheme provides, ie (x y . rest).
;; I'd even live fixed number of arguments if there is an easy way to define
;; macros.
;;
;;
;;
;; *** Ken Anderson: Common Lisp arglist data
;;
;; I put together these statistics from a common lisp application
;;
;; 27,935 Function and macros
;; 6,328 Function or macros with keyword arguments
;;
;; Distribution of number of arguments (no keyword case)
;;
;; 0=1254
;; 1=12961
;; 2=4063
;; 3=1885
;; 4=628
;; 5=302
;; 6=173
;; 7=95
;; 8=69
;; 9=69
;; 10=34
;; 11=18
;; 12=27
;; 13>= 29
;;
;; Distribution of keyword usage:
;;
;; (&KEY)=2048
;; (&OPTIONAL)=1663
;; (&REST)=1176
;; (&BODY)=988
;; (&KEY &REST)=217
;; (&ALLOW-OTHER-KEYS &KEY)=60
;; (&REST &OPTIONAL)=51
;; (&KEY &OPTIONAL)=48
;; (&ALLOW-OTHER-KEYS &KEY &REST)=43
;; (&KEY &REST &OPTIONAL)=9
;; (&BODY &OPTIONAL)=6
;; (&REST &WHOLE)=6
;; (&BODY &WHOLE)=4
;; (&AUX)=4
;; (&ALLOW-OTHER-KEYS &REST &OPTIONAL)=2
;; (&OPTIONAL &WHOLE)=1
;; (&AUX &KEY)=1
;; (&WHOLE)=1
;;
;; From this i'd conclude that most functions have 3 or less arguments and
;; that keywords are used less than about 1/3 of the time.
;;
;; &key seems to be used as much as &optional and &rest combined.
;;
;;
;;
;; *** David Morse: strings implemented as lists
;;
;; In one of your arc articles you said you thought it "might be useful"
;; to have strings be implemented as lists.
;;
;; The benifits I can think of would be:
;;
;; * (subseq /str/ :start /n/) doesn't cons
;; * can share substructure among strings
;; * easy insert onto front of strings
;;
;; The second and third don't seem like they'd be all that handy.
;;
;; The first is attractive. Because its "arrays" are untagged, C strings
;; already have this property. Its often nice there. On the other hand,
;; using CL's :start and :end parameter passing pattern doesn't fill me
;; with dread either.
;;
;; It seems like a tradeoff between tripling the number of parameters to
;; string functions versus approximately octupling the heap usage of
;; strings.
;;
;;
;;
;; *** Todd Proebsting: Pronouns
;;
;; Your comments on pronouns and iteration captures remind me of some
;; ideas that Ben Zorn and I threw around a few years back; you may find two TRs
;; interesting. One describes "shorthands" (pronoun-like things) and the other
;; describes "histories" (capture-like things):
;;
;; ftp://ftp.research.microsoft.com/pub/tr/tr-2000-03.ps
;; ftp://ftp.research.microsoft.com/pub/tr/tr-2000-54.ps
;;
;;
;;
;; *** Stephen Ma: Strings as Lists
;;
;; Strings as lists: seems you just want to scan the string from left
;; to right, which is what the car and cdr functions let you do.
;;
;; Instead of that, how about storing strings as vectors of bytes,
;; and using "scanners":
;;
;; (a) A scanner is a mutable object that contains a string and a
;; current position within that string. String-matching functions
;; update the current position. Make a new scanner with
;; "(sc )".
;;
;; (b) A scanner is completely distinct from its string:
;; a string can have any number of scanners attached to it, and
;; a scanner can be reattached at any time to another string.
;;
;; (c) Scanners will be especially useful with the "match" macro,
;; which works a lot like Unix's Lex utility:
;;
;; (match
;;
;;
;; else )
;;
;; This attempts to match one or more regular expressions against
;; 's current position. If one of the s match,
;; the corresponding gets executed. A successful match
;; advances the scanner's current position past the matched
;; string.
;;
;; In each , the pronouns $1, $2, ..., et cetera refer to
;; matched substrings, just like Perl. $& refers to the entire
;; matched string.
;;
;; In keeping with Arc's "make it easy" philosophy, if
;; is not a scanner but a string S, then S is implicitly replaced
;; by (sc S 0). So it's easy to do a quick match against a
;; string.
;;
;; As I mentioned, a single invocation of "match" works much like
;; an instance of Lex, and like Lex can be precompiled to run
;; blazingly fast. Using more than one "match" lets you scan
;; strings in very powerful, context-dependent ways.
;;
;; (d) Contrived example. Here's a function on a string s that
;; prints the initials of all the words inside s,
;; and returns the sum of all the integers inside s.
;; (Assume Perl-style regexps.)
;;
;; (fn scan (s)
;; (= scanner (sc s 0))
;; (while (match scanner
;; "\s+" t ;Ignore whitespace
;; "(\w)\w*" (do (pr $1) t) ;Print the word's initial.
;; "\d+" (do (sum $&) t) ;Accumulate numeric sum.
;; "$" nil))) ;End of string terminates loop.
;;
;; Thus (scan "alpha 2 7 beta 8") prints "ab" and returns 17.
;;
;;
;;
;; *** Ray Blaak: Implicit Local Vars
;;
;; I believe automatic variable introduction will hinder the programmer
;; more than help. "Expert" programmers type fast, and slightly mistyped
;; variable names would be hard to find visually, and there would be no
;; language support to detect them. This will make debugging much more difficult.
;;
;; Instead, make the syntax for binding variables be succinct and clear (e.g.
;; as you have done with let). Perhaps allow a (def var value) form. The point is
;; that declaring bindings should be inexpensive to the programmer while still
;; allowing undeclared name detection.
;;
;; I want my languages to be powerful and flexible, and easy to type, but I
;; also want decent error checking from my language environment as well. If there
;; is no other error detection in a language environment, *the* thing that I have
;; found important in almost 20 years of programming, more than type checking,
;; parameter matching, etc., is the reporting of unknown names.
;;
;; My advice and plea: don't create local variables implicitly.
;;
;;
;;
;; *** Ray Blaak: Use of *fail*
;;
;; A cool hacker's language always needs to balance expressivity, ease-of-use,
;; and safety.
;;
;; With regards to the use of *fail* for db lookups, I believe there is a
;; better way.
;;
;; The problem with the use of a global variable to indicate the special
;; failure value is that it is not thread safe (Arc will be supporting threads
;; eventually, no?), and can lead to insidious bugs if some code fails to
;; restore the global properly. The code required to make it thread safe is
;; tedious and requires the programmer to be aware of potential problems on
;; every lookup.
;;
;; Furthermore, if a non-default fail value is needed, the programmer must do
;; the *fail* override on every call, which is also tedious.
;;
;; If instead one realizes that the fail value is a property of the db itself,
;; one can instead specify it when the db is created, perhaps with a :failure
;; keyword, that if omitted defaults to nil. Then different db's can have their
;; own notion of fail values simultaneously without interfering with each
;; other.
;;
;; Usage is then easier (all lookups require the same, uniform work), safer,
;; and expressivity is actually improved since things can compose better.
;;
;; Alternatively, one could also specify the fail value as an optional
;; parameter on a lookup call.
;;
;; Note also that the idea of keyword parameters is in general a better way to
;; "fiddle" with settings, giving the control that hackers love while avoiding
;; the problems that special global control variables give rise to.
;;
;;
;;
;; *** Shiro Kawai: M17N
;;
;; Is there any plan for Arc to support multilingualization
;; (M17N)? Traditionally, M17N is considered by language designers
;; as some sort of add-on, library-level stuff. Yet it is
;; indispensable for the real world applications that are used
;; worldwide, and I think it does affect the implementation
;; decision of the language core to some degree, if you want efficiency.
;; In fact, out of frustration to the existing implementations
;; I've even written my own Scheme that supports multibyte strings
;; natively to do my own job.
;;
;; Why is it important? Since the choice of implementation does
;; affect the programming style.
;;
;; There may be some possibilities:
;;
;; (a) A string is just a byte array. Application is responsible
;; to deal with multibyte characters. (It's pretty much
;; the situation until recently).
;;
;; (b) A string is an array of wide characters, e.g. UCS-4.
;; (Note: UCS-2 is not enough).
;; The stream converts internal representation and external
;; representation. Java's going to this way, and I think
;; Allegro CL also adopts this after version 6.0.
;;
;; (c) A string may contain multibyte characters, e.g. UTF-8,
;; or more complex structure that uses, for example, a
;; struct of language tag and byte vector.
;; String access by index is no longer a constant operation,
;; and a destructive change of string may be much heavier
;; than just a destructive change of a vector.
;; I think Python is going this way, as well as some other
;; popular scripting languages.
;;
;; The approach (b) is simple and just works, and may be enough
;; for Arc's purpose. However, in some cases it doesn't works well,
;; especially when (1) you have to deal with large amount of text
;; data that mostly consists of single-byte characters and not want
;; to consume as 4 times of memory as byte string, and (2) you have
;; to do lots of text I/O, for most of external data will likely
;; be stay encoded in variable-length (multibyte) characters and
;; you have to convert them back and forth.
;;
;; The approach (c) solves those problems, but it affects the
;; programming style. You tend to avoid random access of
;; string. Searching in string performs better if it directly
;; returns substring rather than indices.
;; Allocating a string by make-string and using string-set!
;; to fill it by a character at a time is a popular technique in
;; Scheme to construct a known-length string, but it behaves
;; extremely poorly in this implementation. I tend to use
;; string ports heavily and then the penalty of non-constant
;; access diminishes. Another advantage of this approach is
;; that you can have "double-view" of a string, one as a
;; sequence of characters and the other as a sequence of bytes,
;; which is convenient to write an efficient code to deal with
;; packets that mixes binary data and character data.
;;
;;
;;
;; *** Vinay Gupta: Python, XML, SQL
;;
;; I use Python quite frequently. Although I can't point to specific
;; features I think you should duplicate in Arc, I can think of specific
;; aesthetics which you should:
;;
;; 1> fixed code style with minimal punctuation
;; python's use of indentation (only) to mark blocks, and move towards to
;; banning of tabs, really does help move code between programmers and
;; encourage both reuse and learning-by-inspection. All python code looks
;; basically the same.
;;
;; 2> easy language support for putting basic documentation in code files
;; (python does it very nicely, with tools for pulling it all together
;; later).
;;
;; A nice extension to that would be to have support for XML in the code
;; comments, so you can yank the XML of the comments out then format it at
;; whim without having to feed the text you pulled out of the code through
;; Word or some other manual step where things can get out of step.
;;
;; On another note, I want to suggest that you seriously think about how
;; you build your interface to SQL into the system.
;;
;; At this point, SQL is present on just about all servers in some form,
;; and Mac OS X is really beginning to push it down into the desktop.
;;
;; But at present, access to SQL is rather a bolt-on in most languages, in
;; particular relative to file system access which is much more tightly
;; integrated.
;;
;; I'd like to suggest that you consider integrating SQL support at much
;; the same level as file system support: as a conceptually integrated part
;; of the language design. I don't know quite where that might go, but I
;; suspect it to be a very interesting direction (particularly if the
;; abstraction which supports filesystems and SQL-based databases could be
;; extended to other, less common forms (XML databases being the obvious
;; one) by users).
;;
;;
;;
;; *** Will Duquette: What CL Misses
;;
;; What I'd like that I missed in Common Lisp.
;;
;; 1. Standard control structures. From what I can see, you've already
;; got this well under.... Well, under control, I guess.
;;
;; 2. Standard notation. As you comment, Unix won. It would be nice
;; to see standard notation for character constants (e.g., '\n' for
;; newline) and for format strings. "~A" isn't wrong, but C, C++,
;; Perl, Python, Tcl, awk, and so forth can all use C's sprintf format
;; strings.
;;
;; These conventions might not be perfect, but they are familiar to
;; vast number of programmers.
;;
;; 3. Better string processing. I particularly like Tcl's variable and
;; command interpolation. For example, here's an interactive Tcl
;; session that defines a variable and a function, and interpolates
;; both into a string.
;;
;; % set a "Hello"
;; Hello
;; % proc f {} {return "World"}
;; % set b "$a, [f]!"
;; Hello, World!
;;
;; You're contemplating treating strings as lists where each character
;; is an element. One of the real conveniences of Tcl is that almost
;; any string can be manipulated as a list of white-space delimited
;; tokens. The "split" command can split up a string into a list of
;; tokens on any set of delimiters. This is, practically speaking,
;; incredibly useful. Common Lisp falls down here in two ways:
;;
;; * There's no equivalent of the "split" command. (I've seen the
;; discussions about "partition", currently defined on cliki;
;; the word "over-engineered" comes to mind.) Anyway, the point isn't
;; that this can't be done in CL; just that it should be provided.
;;
;; * You can't easily use a CL list of symbols as a proxy for a
;; string of white-space delimited tokens; the list of symbols has
;; too many syntactic gotchas, and then there's the whole case thing.
;;
;; Which leads me to 4:
;;
;; 4. Case-sensitivity. Symbol names, especially, should be case sensitive.
;;
;; 5. Associative arrays. Hash tables are incredibly useful, but the
;; syntax to use them should be terse. Some kind of array notation
;; works very well. For example,
;;
;; (= myDB[x] y)
;;
;; assigns y to key x in hash table myDB. Tcl works much like this.
;; You also get multi-dimensioned arrays quite naturally using your
;; propose "x.y" notation: though I would suggest using "," and ";"
;; instead of "." and ":". Why?
;;
;; x,y --> (x y) A cons
;; 1,1 --> (1 1) A cons
;; 1.1 --> 1.1 A floating point number
;;
;; 6. A more standard notation for record structures, or, more specifically,
;; for object members. C/C++/Java/Python syntax has become common for
;; this, and is more terse than either of the CL possibilities.
;;
;;
;;
;; *** Dan Milstein: Concurrency
;;
;; One problem which, IMHO, no popular language has come even
;; close to solving well is allowing a programmer to write multithreaded
;; code. This is particularly important in server-side programming, one of
;; Arc's major targets. I've written a good deal of multithreaded Java, and
;; the threading model is deeply, deeply wrong. As a programmer, there's
;; almost no one way to write the kind of abstractions which let you forget
;; about the details. You're always sitting there, trying to work through
;; complicated scenarios in your head, visualizing the run-time structure of
;; your program.
;;
;; I didn't see another way until I read John H. Reppy's "Concurrent
;; Programming in ML". Instead of building his concurrency constructs around
;; monitored access to shared memory, he builds them around a message passing
;; model (both synchronous and asynchronous). What's more, he provides
;; powerful means of capturing a concurrent pattern in an abstraction which
;; hides the details.
;;
;; I highly recommend giving that book a read. Here's an example of some of
;; what you get (not the abstraction, actually, just the basic power of
;; message-passing over shared memory). The abstraction facilities are
;; complex enough that, like Lisp macros, a small example doesn't really
;; capture their power. I'm in no way familiar with concurrent extensions to
;; Lisp, so I'm not able to provide the code for how much harder it would be
;; in CL or Scheme. Assuming they were augmented with a shared memory model
;; (as Java is), which forces the programmer to deal with synchrnoized access
;; to memory, I can only imagine it would be significantly more complex.
;;
;; A producer/consumer buffer. You want a buffer with a finite number of
;; cells. If a producer tries to add an element to a full buffer, it should
;; block until a consumer removes an element. If a consumer tries to remove
;; an element from an empty buffer, it should block until a producer adds
;; something.
;;
;; In Concurrent ML:
;;
;; datatype 'a buffer = BUF of {
;; insCh : 'a chan,
;; remCh : 'a chan
;; }
;;
;; fun buffer () = let
;; val insCh = channel() and remCh = channel()
;;
;; fun loop [] = loop [recv inCh]
;; | loop buf = if (length buf > maxlen)
;; then (send (remCh, hd buf); loop (tl, buf))
;; else (select remCh!(hd buf) => loop (tl buf)
;; or insCh?x => loop (buf @ [x]))
;;
;; in
;; spawn loop;
;; BUF{
;; insCh = insCh,
;; remCh = remCh
;; }
;; end
;;
;; fun insert (BUF{insCh, ...}, v) = send (insCh, v)
;;
;; fun remove (BUF{remCh, ...}) = recv remCh
;;
;; ---------------
;;
;; Translated into a Lisp-ish syntax (very easy to do from ML), this would
;; look something like:
;;
;; (defstruct buffer
;; ins-ch
;; rem-ch)
;;
;; (defun create-buffer ()
;; (let ((ins-ch (make-channel))
;; (rem-ch (make-channel)))
;; (labels ((loop (buf)
;; (cond ((null buf)
;; (loop (list (recv ins-ch))))
;; ((> (length buf) maxlen)
;; (send rem-ch (car buf))
;; (loop (cdr buf)))
;; (t
;; (select
;; (rem-ch ! (car buf) => (loop (cdr buf)))
;; (ins-ch ? x => (loop (append buf (list x)))))))))
;; (spawn #'loop)
;; (make-buffer :ins-ch ins-ch :rem-ch rem-ch))))
;;
;; (defun insert (b v)
;; (send (buffer-ins-ch b) v))
;;
;; (defun remove (b)
;; (recv (buffer-rem-ch b)))
;;
;;
;; Key things to notice:
;;
;; 1) Language features:
;;
;; Communication between threads *only* occurs over channel objects, which can
;; be thought of as one-element queues. In CML, channels are typed, but in
;; Lisp they probably wouldn't be.
;;
;; send/recv: synchronous (blocking) communication over the channel. A thread
;; can attempt to send an object over the channel, and will then block until
;; another thread does a recv on the channel.
;;
;; Creating a new thread is done via 'spawn', which takes a function as its
;; argument. (I can't remember what the signature of that function is
;; supposed to be -- clearly, in this case it can't be a function of no
;; arguments, but imagine it to be something like that).
;;
;; Selective communication: the call to 'select' is one of the very powerful
;; features. It is like a concurrent conditional -- it simultaneously blocks
;; on a list of send/recv calls, and executes the associated code with
;; whichever call returns first (and then drops the rest of the calls). The !
;; syntax means an attempt to send, the ? means an attempt to receieve. In
;; both cases, the '=>' connects the associated code to execute. (I haven't
;; really come up with a Lispy translation of that syntax).
;;
;; I don't think select could be efficiently implemented without language
;; support. It requires a sort of 'partial blocking', which is tricky to
;; implement on top of normal blocking.
;;
;;
;; 2) The Idiom
;;
;; The buffer is implemented as a separate thread which has connections to two
;; channels and an internal list to keep track of the elements of the buffer.
;; This thread runs through a loop forever, taking the current state of the
;; buffer as its argument, and waiting on the channels in the body of its
;; code. It is tail-recursive.
;;
;; Note the absolute lack of any code to deal with synchronization or locking.
;; You might notice the inefficient list mechanism (that append is going to
;; get costly in terms of new cons cells), and think that this is only safe
;; code because of the inefficient functional programming style. In fact,
;; that's not true! The 'loop' function could desctructively modify a list
;; (or array) to which only it had access. There would still be no potential
;; for sync'ing problems, since only that one thread has access to the
;; internal state of the buffer, and it automatically syncs on the sends and
;; receieves. It's only handling one request at a time, automatically, so it
;; can do whatever it wants during that time. It could even be safely
;; rewritten as a do loop.
;;
;; What I find so enormously powerful and cool about this is that the
;; programmer doesn't need to worry about the run-time behavior of the system
;; at all. At all. The lexical structure of the system captures the run-time
;; behavior -- if there is mutating code inside of the 'loop' function, you
;; don't have to look at every other function in the file to see if it is
;; maybe modifying that same structure. This is akin to the power of lexical
;; scoping over global scoping. I have never seen concurrent code which lets
;; me ignore so much.
;;
;; This really just scratches the surface of Concurrent ML (and doesn't touch
;; on the higher-level means of abstraction). But I hope it gives a sense of
;; how worthwhile a language it is to learn from.
;;
;;
;; 3) Issues
;;
;; I think that channels themselves would be fairly easy to implement on top
;; of the usual operating system threading constructs (without needing a
;; thread for each one). However, the style which this message-passing model
;; promotes can easily lead to a *lot* of threads -- if you have a lot of
;; buffers, and each of them has its own thread, things can get out of hand
;; quickly. I believe that Mr. Reppy has explored these very issues in his
;; implementation of CML.
;;
;; http://cm.bell-labs.com/cm/cs/who/jhr/sml/cml/
;;
;; Insofar as I have time (which, realistically, I don't) I would love nothing
;; more than to play around with implementing CML'ish concurrency constructs
;; in a new version of Lisp like Arc.
;;
;;
;;
;; *** Ben Evans: Adjustable Competence
;;
;; One idea which I've been thinking about a lot lately is "use strict;"
;; in Perl.
;;
;; It's an example of how to write a general purpose language which can
;; still speak to the top of the intelligence curve of users.
;;
;; What I was thinking of is a language with a directive to change the
;; competency level of a piece of code.
;;
;; For example, in an imaginary Perlish language called Gimbal:
;;
;;
;; #!/usr/bin/gimbal
;;
;; use beginner;
;;
;; {
;; variables = "by default have lexical scope in beginner mode";
;;
;; global VAR = "I must be prefigured by keyword global, and my name must
;; all be in upper case in this mode, otherwise, compile-time errors occur";
;;
;; print variables + "\n";
;; }
;;
;; print VAR + "\n";
;;
;; use competent;
;;
;; global dog = "I will generate a compile-time warning because my name
;; is not all in capitals in competent mode";
;;
;; use expert;
;;
;; scope global;
;;
;; cat = "I generate no warnings at all, and the keyword global is not
;; required because I changed the default scope with the scope keyword";
;;
;; ....
;;
;; Having a competency level pragma means that real hackers can get on
;; with their real work, while still having something which students etc
;; can use.
;;
;; If this was combined with a code signing system (Eg, in 'use beginner'
;; mode, you can't use a class which isn't signed by someone who you can
;; establish a trust relationship to according to the keyring for your
;; local language install) then it might look a lot more appealing to the
;; large, mediocre hordes of programmers out there.
;;
;;
;;
;; *** James Bullard: sequences, and range parameters.
;;
;; One thing I especially like about Python are the
;; primitives used to specifiy range. For instance,
;;
;;
;; >> seq = [1,2,3,4,5]
;; >> seq[1:2]
;; [2]
;; >>> seq[1:3]
;; [2,3]
;;
;; I could see this being easily incorporated into your
;; 'sequences are an implicit method on indices' by also
;; adding 'and ranges'. Sytax, such as:
;;
;; >> ("something" (1 . 3))
;; (o m)
;;
;; Is a possibility. Mostly, I just wanted to suggest a
;; feature which I use all the time in Python.
;;
;;
;;
;; *** Trevor Blackwell: Databases
;;
;; Databases are an easy, low-risk way to store and index lots of data
;; without having to design a custom system for each kind of data.
;;
;; When you store data in files, it's hard to get good
;; performance. Usually you either end up reading many files at each
;; click, or reading them all in at startup time and taking a lot of time
;; and memory.
;;
;; Databases also ensure correct concurrent access, so you can have
;; multiple users working simultaneously on the same data without
;; conflicts.
;;
;;
;;
;; *** Eric Tiedemann: Python Syntax
;;
;; Python is one of my languages of choice at the moment because of it's
;; terse, simple, and regular syntax. Those attributes could come in
;; handy for a macro-friendly syntax-for-Lisp. esr has a continuing
;; interest in this subject.
;;
;; As far as I can figure, *all* statements in Python (aside from import
;; and print) are either expressions or assignments (which we could
;; `promote' to expressions) or have one of the two forms:
;;
;;
;; :
;;
;; Where -> simple_stmt | NEWLINE INDENT stmt+ DEDENT
;;
;; This even includes class definitions!
;;
;; The major complexity I can see is that some macro expressions (e.g.,
;; if, try) would want to incoporate expressions *after* their containing
;; expression (e.g., else, except). This could be handled by have macros
;; (optionally) take and return both an expression and an `expression
;; continuation'.
;;
;;
;;
;; *** Guyren Howe: OOP
;;
;; In response to your request for new ideas for Arc, I'm going to mention an
;; OOP feature from the language REALbasic ().
;;
;; It's a new type of class extension mechanism: as well as allowing for
;; overloading/method overriding, a class can define a New Event that allows it
;; to call its subclasses. An event declaration is just a function header.
;;
;; The most immediate subclass to implement a handler for the event traps the
;; event and makes it disappear for further subclasses, unless the class that
;; defined the handler re-defines and calls the event with the same name.
;;
;; The result is that rather than extension by uncontrolled, ad-hoc overriding,
;; you get extension through a well-defined protocol.
;;
;; It's a nice mechanism.
;;
;; Example: you have a NiceButton object. A TextNiceButton is defined that
;; writes text onto the face of the button.
;;
;; Now you want to draw the NiceButton in a different way (with a gradient,
;; say).
;;
;; If TextNiceButton was written with traditional overloading, it might be that
;; the drawing of the text happens at the wrong time, and if you try to draw
;; the gradient you might overwrite the text. But if TextNiceButton was
;; responding to a DrawText event issued by NiceButton, you can control when it
;; is drawing its text, so you can make sure you've drawn your gradient first.
;;
;; When I describe this to people, they react by saying that it is strictly
;; weaker than overriding methods, and this is true. But for most purposes,
;; having a well-defined protocol is nice.
;;
;;
;;
;; *** Sam Tregar: Perl Community
;;
;; You mentioned the Perl library many times but rarely mentioned the Perl
;; community. It's quite obvious to me that Perl would not be where it is
;; today, with the library it has today without the Perl community. Also,
;; from reading Larry Wall's various speeches and essays it's obvious to me
;; that the Perl community is no accident. Larry designed the Perl community
;; and the result is the powerhouse that's resulted in the Perl we know
;; today. Simply: the Perl library was not carefully designed; the Perl
;; community was carefully designed and the Perl community created the Perl
;; library. Perhaps this is a lesson Arc can follow?
;;
;;
;;
;; *** Drew Csillag: Misc Suggestions
;;
;; You should be able to call a function with keyword arguments without
;; having to define the function to be able to take them (Python vs. CL)
;;
;; Reference counted GC is a great thing (but still needs some
;; supplemental GC to pick up the cyclic trash) because it's very
;; predictable which is very useful if you've ever had to open up a bunch
;; of files in a tight loop before.
;;
;; Multiple inheritance is a useful thing. Not often, but there are a
;; number of times it can save you a bunch of headaches. Especially for
;; mixin classes.
;;
;; Also, builtin types should be largely indistinguishable from user
;; classes. You should be able to write a class in such a way that you
;; could do (+ userob1 userob2) and there would be a method in either one
;; or the other (maybe both) object's class to handle this.
;;
;; Introspection into the system is a wonderful thing. Being able to
;; write a profiler and debugger for your language in your language is an
;; great thing to be able to do. It allows all sorts of cool tracing and
;; debugging (coverage analysys) things you'd ever want to do. Being
;; able to get a hold of the namespaces you are executing in is also a
;; huge boon I learned from Python. If you can also introspect into the
;; compiled forms of functions (assuming that they compile to some
;; bytecode object) is a great thing too.
;;
;; Some of the iteration stuff seems a bit ooky to me though. While,
;; with the it binding is cool, but part of it doesn't sit well with me.
;; Perhaps because you wouldn't be able to get at it if you are in a
;; nested while loop or something. Also each with keeps is more of a
;; filtering function than straight iteration (like Python's filter()).
;;
;; As for things like scheme-like continuations, for me it's hard to say
;; yes, but hard to say no because they are useful for building exception
;; handling systems (if you don't include some kind of exception handling
;; system (built with or without explicit continuations) -- which you
;; should -- runtime errors should raise exceptions, not just halt the
;; system) and microthreading systems.
;;
;; The interpreter should also be able to be multithreaded, but unlike
;; Java, it shouldn't force it on you. I'm not big on multithreading in
;; general, but sometimes it actually is the best way to do things.
;;
;; Sather-like (I think it's Sather) generators are also very nice things
;; to have.
;;
;; One last suggestion: the interpreter should be written in C. Language
;; systems (with the exception of C) that self host are a pain in the
;; neck.
;;
;;
;;
;; *** Thomas Baruchel: Call/cc vs. Exceptions
;;
;; Though call/cc is better than exceptions, I think it's much easier
;; to use exceptions than call/cc. Why ? Because you can more easely give a name
;; to an exception (after having declared it) and catch it. Do you see what
;; I mean? What is very clean in OCaml is the structure:
;;
;; OBtry
;; ...
;; ...
;; with
;; Division_By_Zero -> ... ;
;; IncoherentParameter -> ...;
;; FunnyResult -> ...;
;; WhyDidYouTryThat -> ...
;; (ie you can put in a separate place everything that can be raised as an
;; exception and handle with it separately).
;; I think that something as powerful as call/cc but as convenient to use
;; as try/with would be a great idea ;-)
;;
;; Another limitation of Scheme is that it isn't intended to implement new
;; types (or at least, it isn't very easy to do it). I think that many
;; languages do it better (OCaml, or even C). That is a big lack:
;; I am now playing with quantum computation, and found it is very easy
;; to implement a 'qubit' type in C or in OCaml and not in Scheme (what I do
;; is use a pair of two complex numbers, and it isn't bad, but...)
;; On the same idea, some languages allow definition of functions with
;; several return values (not necessarely in a structure), by
;; declaring input and output values of the function. This is quite
;; useful for some purposes.
;;
;; Prolog: why not implement some declarative aspects?
;; (at least the lisp 'amb' function, but implemented at a low level, which
;; would make it easier to use (amb-fail isn't a so good idea: Prolog
;; doesn't use anything like 'amb-fail'; whenever a condition isn't satisfied
;; it does the same thing by itself and the programmer hasn't to care about it).
;; Another thing you can't do when using 'amb' after having implemented it by
;; yourself in Scheme is using several 'amb' declarations nested...
;;
;; Think that some tools are more than tools and almost are languages.
;; A CLP(FD) solver has been implemented in GNU/Prolog and it isn't a
;; bad idea... But this has to be done by considering the general concepts
;; of the language. clp(fd) suits well the declarative aspects of the
;; Prolog.
;;
;; Forth like languages: the concept of stack is really impressive,
;; because you can play with much data without using any variables.
;; MY CREDO: a good language doesn't have to use variables. I like
;; functionnal languages for that; I also like Forth (and postscript)
;; for the same reasons.
;;
;;
;;
;; *** David Sloo: Strings
;;
;; The fact that strings behave as lists is convenient. It means there is a
;; one category less to memorize.
;;
;; However, one of the problems I keep running into in language interop is
;; string processing, even in Perl. Everytime I move a string from a module
;; in language X into an application, I have to write a UTF8 processor.
;; Worse, half the time I need to use someone else's code within an
;; application in the same language, I have to check for Shift-JIS, or do
;; UTF8 processing, or some similar dopiness. A string in the language
;; should be treated as an array (in Arc, a list) of Unicode characters no
;; matter what. There are a few good things about C#, and this is one of
;; them. There are a few bad things about Perl, and this is also one of
;; them.
;;
;; Also, I think you made a logical decision in scoping the iterators
;; locally in for loops, but it does mean you need extra stuff for this
;; common idiom, where you preserve the exit-state of the loop:
;;
;; for (int i = 0; i < 10; ++i)
;; if (array[i] == UNSNOOGLE)
;; break;
;;
;; printf("The array of snoogles had a un-snoogle at spot %d", i);
;;
;; I suppose it's worth changing, given the downside.
;;
;;
;;
;; *** Dave Moon: S-expressions are a bad idea
;;
;; I want to comment on your use of S-expressions, based on what I learned
;; in my couple of years researching Lisp hygienic macro ideas and working
;; on Dylan macros. Summary: I learned that S-expressions are a bad idea.
;; There are three different things wrong with them, none of which have
;; anything to do with surface syntax. Having as a convenient abbreviation
;; a surface syntax different from the program representation that macros
;; work on is a fine thing to do.
;;
;; [1] The (function . arguments) notation is not extensible. In other
;; words, there isn't any place to attach additional annotations if some
;; should be required. 20 years ago it was noticed that there is no place
;; to attach a pointer back to the original source code, for use by a
;; debugger. That's just one example. This is easily patched by changing
;; the notation to (annotation function . arguments), where annotation is a
;; property list, but this is a bit awkward for macro writers. The next
;; point suggests a better fix.
;;
;; [2] Representing code as linked lists of conses and symbols does not lead
;; to the fastest compilation speed. More generally, why should the
;; language specification dictate the internal representation to be used by
;; the compiler? That's just crazy! When S-expressions were invented in
;; the 1950s the idea of separating interface from implementation was not
;; yet understood. The representation used by macros (and by anyone else
;; who wants to bypass the surface syntax) should be defined as just an
;; interface, and the implementation underlying it should be up to the
;; compiler. The interface includes constructing expressions, extracting
;; parts of expressions, and testing expressions against patterns. The
;; challenge is to keep the interface as simple as the interface of
;; S-expressions; I think that is doable, for example you could have
;; backquote that looks exactly as in Common Lisp, but returns an
;; rather than a . Once the interface is separated from
;; the implementation, the interface and implementation both become
;; extensible, which solves the problem of adding annotations.
;;
;; So you don't get confused, I am not saying that Dylan macros provide a
;; good model of such an interface (in fact that part of Dylan macros was
;; never done), nor that Dylan macros necessarily have any ideas you should
;; copy. I'm just talking about what I learned from the Dylan macros
;; experience. Actually if you succeed in your goals it should be
;; straightforward for a user to add Dylan-like macros to Arc without
;; changing anything in Arc.
;;
;; Maybe someday I can explain to you the representation of programs I used
;; in the Dylan compiler I wrote (never finished) after I left Apple. It
;; has some clever ideas so that it is efficient in terms of consing and the
;; same representation can be used in all levels of the compiler from the
;; surface syntax parser down to the machine code generator. I'd have to
;; retrieve the code from backup first.
;;
;; [3] Symbols are not the right representation of identifiers. This
;; becomes obvious as soon as you try to design a good hygienic macro
;; system. This is really another case of failing to separate interface
;; from implementation. A symbol can be a convenient abbreviation, but in
;; general an identifier needs to be a combination of a name and a lexical
;; context. Because of macros, the structure of lexical contexts is not
;; simple block-structured nesting: an identifier can be referenced from a
;; place in the code where it is not visible by name. Also an identifier
;; can be created that doesn't have a name, or equivalently isn't visible
;; anywhere just by name, only by insertion into code by a macro.
;;
;; So I think you should have an internal Arc-expression representation for
;; programs, and a surface syntax which is more compact and legible, but
;; Arc-expressions should not be specified to be made out of conses,
;; symbols, and literals. Arc-expressions should be defined only by an
;; interface, which should be open (i.e. new interfaces can be added that
;; apply to the same objects). The implementation should be up to the
;; compiler writer and there should be room for experimentation and
;; evolution. Interesting question: is there a surface syntax for
;; Arc-expressions different from the abbreviated surface syntax, and if so,
;; what is it?
;;
;; Other unrelated comments:
;;
;; "Here are a couple ideas:
;; x.y and x:y for (x y) and (x 'y) respectively."
;;
;; Do you mean x.y stands for (y x)? Oh, I see, you have field names as
;; indices rather than accessors, so you actually meant x.y stands for (x
;; 'y).
;;
;; As for x:y, I think what Dylan borrowed from Smalltalk is the right
;; answer, thus x: stands for (quote x). Colon as a postfix lexical
;; "operator" works surprisingly well.
;;
;; "local variables can be created implicitly by assigning them a value. If
;; you do an assignment to a variable that doesn't already exist, you
;; thereby create a lexical variable that lasts for the rest of the block."
;;
;; This is a really bad idea, because inserting a block of code that
;; includes a local variable declaration into a context where a variable
;; with that name already is visible changes the declaration into an
;; assignment! Or if you fix that by making an assignment at the front of a
;; block always do a local declaration instead of an assignment, then when
;; you put code at the front of a block you have to remember to stick an
;; "onion" in front of that code if there is any chance that the code being
;; inserted could be an assignment.
;;
;; Weird context-dependent interpretation of expressions like that makes a
;; language harder to use, both for programmers and for macros. It's one of
;; the problems with C, don't put it into Arc too.
;;
;; I'm not saying that you need to use Common Lisp's let for local
;; declarations. One possibility would be to use = for declaration, := for
;; assignment, and == for equality. Another would be to use = for all
;; three, but with a prefix set for assignment and let for declaration.
;; Other possibilities abound.
;;
;; But then later you introduce a let macro, so I don't know what you really
;; think about local declaration.
;;
;; "Making macros first-class objects may wreak havoc with compilation."
;;
;; That depends entirely on whether it is permissible to write functions
;; that return macros as values and permissible to pass macros as arguments
;; to functions that are not locally defined (or directly visible fn
;; expressions), or whether all macros are directly visible at compile-time
;; as initial values of variables. I think you should limit the language to
;; what you know how to implement, so the macro special-form should only be
;; allowed in places where its complete flow is visible at compile time and
;; should never be allowed to materialize as a run-time object. You need a
;; different way to create a macro object that exists in the run-time in
;; which macros run, the compile-time run-time. You need to define
;; precisely "flow visible at compile time," possibly being very restrictive
;; and only allowing what we really know is needed, namely a macro special
;; form can be used in function position, as an argument in a function call
;; where the function is a fn special form, in the initial value of a global
;; constant (not variable!), and nowhere else. This is tricky but tractable
;; I think.
;;
;; "strings work like lists"
;;
;; does rplaca [probably (= (car x) y] work on strings? What about rplacd?
;;
;; "Overload by using a fn as a name."
;;
;; I think you need to rethink this way of defining methods, it has a lot of
;; problems.
;;
;;
;;
;; *** Dave Moon: Object-Oriented
;;
;; Re http://www.paulgraham.com/reesoo.html
;;
;; When I say object-oriented, I am often referring to yet a different
;; property, which I think is a good property for most languages to have.
;; It's not the same as your "5.Everything is an object" although it might
;; sometimes be called "Everything is an object":
;;
;; Things are independent of their names. To put it another way, as much as
;; possible of the machinery is exposed as an object that gets named by
;; binding an identifier to it, and you operate on the object, not on the
;; name. Classes work this way in CLOS, they don't work this way in C++.
;; Modules work this way in Dylan, modules (packages) don't work this way in
;; Common Lisp, modules (packages) almost but don't quite work this way in
;; Java. Method invocation works this way in CLOS (generic functions are
;; objects), it doesn't work this way in Smalltalk and Objective C (method
;; selectors are like Lisp symbols). I think most things done in Scheme
;; work this way.
;;
;; Arc probably follows this principle even though you claim it's not
;; object-oriented.
;;
;; One advantage is if you don't like the name of something you can rename
;; it by manipulating identifier bindings; there are no or few reserved
;; words. (I decided that "reserved words" are words that we don't want to
;; hear our children say.)
;;
;; Another advantage is you can make things anonymous. It also might become
;; easier to expose the guts of the language for extension by users ("meta
;; objects").
;;
;; Another advantage is the language gets the conceptual simplicity that
;; comes from making things orthogonal. I think that is the real advantage.
;;
;;
;;
;; *** Dave Moon: Arc Syntax
;;
;; Here is how I would do syntax for Arc or a language like it. I hope you
;; find these ideas useful.
;;
;; The lexical grammar is hard-wired, and is the same for the surface syntax
;; and for the S-expression syntax. I have my ideas about what the lexical
;; syntax should be, but I'll omit them here.
;;
;; The lexical grammar produces only two types of tokens: literals and
;; names. A name can look like an identifier in other languages, but also
;; can look like an operator, a dot, a semicolon, a comma, or even a
;; parenthesis.
;;
;; The meaning of a literal is built into the language. The meaning of a
;; name is defined by a binding. Bindings can be top-level or local. The
;; language comes with a bunch of top-level bindings that define the
;; standard language, but users can add more and can replace the standard
;; ones to customize the language. Top-level bindings should be organized
;; into modules, but that's a separate topic.
;;
;; A top-level binding consists of one or more of the following: a value,
;; which is either an ordinary runtime value or a macro; a type declaration
;; if you allow those; a constant declaration if you allow those; a dynamic
;; binding declaration (special in Common Lisp) if you allow those; a syntax
;; declaration.
;;
;; The phrase grammar for the surface syntax is built up by syntax
;; declarations from the following hard-wired elements:
;;
;; - token - a literal or a name
;; - literal - a literal
;; - string - a character string literal
;; - keyword - a Dylan-like symbol literal, identifier colon
;; - name - a token that is not a literal
;; - word - a name that does not have a syntax declaration
;; - expression - one of:
;; + a literal
;; + a word
;; + a syntax form consisting of a name with a syntax
;; declaration followed by the expected syntax
;; + a compound expression constructed from subexpressions,
;; prefix operators, and infix operators, with ambiguities
;; resolved by operator precedence
;;
;; I think the grammar as declared by syntax declarations has to be LR(1)
;; for this surface syntax project not to be sunk by grammatical
;; ambiguities. That remains to be considered in detail.
;;
;; Note that there is no built-in distinction between statements and
;; expressions. Of course a user could add a syntax form whose body is
;; composed of statements. I wouldn't do that myself.
;;
;; The phrase grammar for S-expression syntax is hard-wired. I won't
;; discuss it in this email except to use square brackets to indicate
;; S-expressions. Having a syntax for S-expressions is unnecessary except
;; for bootstrapping and debugging, unless some programmers prefer to bypass
;; the surface syntax for unfathomable reasons.
;;
;; There are two forms for syntax declaration: defsyntax and defoperator.
;; These specify how particular constructs in the surface syntax are parsed
;; and converted into S-expressions. They control the parser by
;; establishing bindings of names to syntax declarations. In most cases the
;; name will appear in the S-expression, so the name must also have a value
;; binding to a function or a macro to give the S-expression a meaning.
;;
;; defsyntax declares a syntax form. It is followed by the name that
;; introduces the syntax form and a grammar description for the syntax form.
;; The grammar description implies how to translate the parsed surface
;; syntax into an S-expression.
;;
;; defoperator declares an operator that can be used to make compound
;; expressions, specifies whether it is prefix or infix or both, and for
;; each case (prefix and infix) specifies its operator precedence and a
;; grammar description for what appears to its right, defaulting to
;; expression. defoperator is general enough to define things like C's
;; semicolon and parentheses, see below.
;;
;; defsyntax and defoperator are themselves syntax forms as well as macros,
;; and the grammar description language is general enough to define them.
;; See below.
;;
;; A grammar description is a sequence of items selected from the seven
;; hard-wired elements of the phrase grammar mentioned above, plus literal
;; tokens represented as character strings, plus the following six grammar
;; "constructors":
;;
;; - repeat(grammar) - zero or more repetitions of the subgrammar
;; - optional(grammar) - zero or one repetition of the subgrammar
;; - or(grammar,grammar, ...) - one of the subgrammars
;; - noise(grammar) - the subgrammar is omitted from the S-expression
;; As a special case, noise by itself at the beginning of a grammar
;; description means that the name of the syntax declaration is
;; omitted from the S-expression
;; - recursive(name,grammar) - the subgrammar, but inside the subgrammar
;; the specified name means the same subgrammar
;; - error(string) - report a syntax error
;;
;; Note that the meaning of names in grammar descriptions is not defined by
;; bindings, these are just treated as literal symbols. This is mostly to
;; avoid name conflicts but also might be necessary for bootstrapping
;; reasons. I could have used BNF-like notation with brackets, bars, and
;; stars instead, but I personally find it more readable to use spelled out
;; names and I don't think conciseness is a virtue here since relatively few
;; grammar descriptions will be written.
;;
;; Note that when defining a macro with surface syntax different from the
;; syntax of a function call, you use both defsyntax and defmacro. One
;; defines the translation from surface syntax to S-expressions, the other
;; defines how to compile (or interpret) the S-expression. I suppose there
;; could be a macro that combines the two.
;;
;; Now for some examples to try to make this comprehensible.
;;
;; One way to define a cond-like if "statement" would be:
;;
;; defsyntax if (expression noise("then") expression
;; repeat(noise("elseif") expression noise("then") expression)
;; optional(noise("else") expression))
;;
;; if a then b elseif c then d else e
;; parses into
;; [if a b c d e]
;;
;; If you prefer a more C-style if "statement", with parentheses instead of
;; then as the noise necessary to avoid the syntactic ambiguity that occurs
;; when two expressions are adjacent:
;;
;; defsyntax if (noise("(") expression noise(")") expression
;; optional(noise("else") expression))
;;
;; if (a) b else c
;; parses into
;; [if a b c]
;;
;; You could even tack noise("end") optional(noise) on the end of the first
;; defsyntax if, if you like. Remember noise with no "argument" means the
;; name of the syntax form; noise("if") is not the same if you copy the
;; binding of if to another name, perhaps using modules.
;;
;; The usual multiplication and subtraction operators could be defined this
;; way:
;;
;; defoperator * (infix: 10)
;;
;; defoperator - (prefix: 100, infix: 10)
;;
;; Semicolon could be defined this way, allowing "blocks" to be written as
;; in C except using () instead of {}:
;;
;; defoperator ; (infix: 0, repeat(expression noise(";"))
;; optional(expression))
;;
;; Parentheses could be defined this way (!):
;;
;; defoperator ( (prefix: 1000, noise expression noise(")"),
;; infix: 900, noise
;; repeat(or(keyword expression, expression) ",")
;; optional(or(keyword expression, expression))
;; noise(")"))
;;
;; defoperator ) (error("Unbalanced parentheses"))
;;
;; This says that left parenthesis as a prefix operator is followed by an
;; expression and a right parenthesis, and turns into just the expression,
;; i.e. the usual use of parentheses for grouping. Left parenthesis as an
;; infix operator is followed by a comma-separated argument list, with the
;; option of Dylan-style keyword arguments, and turns into the left operand
;; followed by the arguments, i.e. a function call S-expression. Its
;; precedence of 900 should be higher than anything but dot.
;;
;; Of course the following really has to be written in S-expression syntax
;; for bootstrapping reasons but it makes a good example of complex syntax:
;;
;; defsyntax defsyntax
;; (name
;; noise("(")
;; recursive(grammar, repeat(
;; or("token", "literal", "string", "keyword",
;; "name", "word", "expression",
;; string,
;; "repeat" noise("(") grammar noise(")"),
;; "optional" noise("(") grammar noise(")"),
;; "or" noise("(") grammar repeat(noise(",") grammar) noise(")"),
;; "noise" noise("(") grammar noise(")"),
;; "recursive" noise("(") name noise(",") grammar noise(")"),
;; "error" noise("(") string noise(")"))))
;; noise(")"))
;;
;; I think the implementation of all this should be very straightforward
;; although I haven't tried it myself. It should give users of the language
;; great flexibility to define their own sublanguages and also has the nice
;; property of allowing almost all of the language to be explained in terms
;; of itself. The reason expression is hard-wired is because there would be
;; great apparent complexity and little gain from exposing to users the
;; machinery needed to convert expression grammar into a nonambiguous
;; grammar and to deal with operator precedence.
;;
;;
;;
;; *** Dave Moon: Arc modules
;;
;; Here is what I think about modules, in somewhat disorganized form.
;;
;; David A. Moon wrote (on 1/21/2002 12:00 PM):
;;
;; >The language comes with a bunch of top-level bindings that define the
;; >standard language, but users can add more and can replace the standard
;; >ones to customize the language. Top-level bindings should be organized
;; >into modules, but that's a separate topic.
;;
;; A module is a map from symbols to top-level bindings. Package and
;; namespace are other names that have been used for the same concept.
;;
;; All processing of code is done with respect to a current module.
;; Bindings in that module control how code is parsed, macro-expanded,
;; interpreted, compiled, and code-walked. Printing of code is also done
;; with respect to a current module, if S-expressions are to be converted
;; back into surface syntax and variable references inserted into macros are
;; to be mapped into expressions that would access the same variable from
;; the current module.
;;
;; Common Lisp's approach of modularizing the map from names to symbol
;; objects instead of the map from symbol objects to bindings is wrong. It
;; comes from a 1974 historic context before lexical scoping. C++'s and
;; Java's conflation of modules with classes is wrong. So is C's conflation
;; of modules with files. I don't think Arc needs any
;; private/protected/public/static/extern type of concept.
;;
;; Does Arc need modules? I think so. Modules aren't just for armies of
;; programming morons. Even solo programmers need a way to avoid name
;; conflicts, and if Arc were to become an open-source type of success it
;; would certainly need the ability to load libraries written by many
;; different authors and thus would need a way to avoid name conflicts. A
;; C-like convention with prefixes on symbols, all my symbols are named
;; moon-xxx and so forth, would almost be workable, but modules are more
;; flexible and produce much more readable code.
;;
;; Besides its set of bindings, each module has an export list, which is a
;; list of symbols, and an import list, which is a list of other modules.
;; The visible bindings in a module include not only the ones in the
;; module's own set of bindings, but also the bindings exported by each
;; module from which this module imports. This feature is just an
;; abbreviation, but a very, very convenient one. I don't care whether
;; Dylan's features for selective import and for renaming during import are
;; adopted, but something has to be done to address name conflicts when
;; importing. It could be as simple as taking the one that appears earliest
;; in the import list.
;;
;; When a new module is created, it initially has no bindings of its own,
;; but imports from a standard set of modules including the module that
;; exports the features of the Arc language. The module can then be further
;; modified by executing expressions that call module-manipulation functions.
;;
;; The value of a binding can be a module. As with macros, this is only
;; useful if the value is known at compile time. This allows one to form a
;; heterarchy of modules and follow a path of bindings whose values are
;; modules to traverse that heterarchy. It's probably useful to include a
;; module named com in the default set of bindings visible to a new module;
;; this would allow copying the Java hierarchical naming convention for
;; packages as Arc's naming convention for modules.
;;
;; When a binding is not exported from its module, the binding is still
;; accessible from other modules, you just have to specify the containing
;; module explicitly, perhaps starting from com. If your surface syntax has
;; x.y mean (x 'y), and calling a module with a symbol as argument returns
;; the value of that symbol's binding in that module, then you can use
;; Java's notation and say that com.paulgraham.arc.core.cons(1,2) returns (1
;; . 2) even if cons is not accessible in the current module. This assumes
;; the infix dot operator has higher precedence than the infix parentheses
;; operator and is left-associative so the above expression means (((((com
;; 'paulgraham) 'arc) 'core) 'cons) 1 2).
;;
;; >A top-level binding consists of one or more of the following: a value,
;; >which is either an ordinary runtime value or a macro; a type declaration
;; >if you allow those; a constant declaration if you allow those; a dynamic
;; >binding declaration (special in Common Lisp) if you allow those; a syntax
;; >declaration.
;;
;; I suspect that a top-level binding should also include a setter value,
;; which like the regular value can be either an ordinary runtime value or a
;; macro. Then if the assignment operator's left-hand side refers to a
;; binding, it sets the value of that binding, but if the left-hand side is
;; a call expression whose callee refers to a binding, it calls the setter
;; value of the callee with the arguments from the left-hand side and the
;; value of the right-hand side. There is a special form named setter which
;; accesses the setter value of a binding, and is itself settable. This
;; seems better than doing string-concatenation on identifiers.
;;
;; Of course a binding whose value is a module will have a setter value so a
;; path like com.paulgraham.arc.core.cons can be used on the left-hand side,
;; thus
;;
;; com.paulgraham.arc.core.cons = fn(x,y) x + y
;;
;; means
;;
;; ((setter (((com 'paulgraham) 'arc) 'core)) 'cons (fn (x y) (+ x y)))
;;
;; Of course actually executing that expression would really mess things up!
;;
;;
;;
;; *** Todd Gillespie: Multi-User
;;
;;
;; I was reading 'Being Popular', and the following line arrested my
;; attention:
;;
;; "It could be an even bigger win to have core language support for
;; server-based applications. For example, explicit support for programs
;; with multiple users, or data ownership at the level of type tags."
;;
;; The more I consider the implications of such an approach, the more I love
;; this idea. Multi-user support as a basic part of a language, carried
;; around in the type system. Over the weekend I worked over some rough
;; designs, and I envision a simple version of such like this:
;;
;; 1. All variables have a user id.
;; 2. Most functions operate in a context that has been silently filtered
;; of any values they cannot access. Ideally, in this context programs
;; are written that cannot make incorrect permissions choices. In LISP
;; style, these restrictions are written in LISP and are redefinable.
;; 3. Access to shared variables is handled by the runtime via a MVCC
;; locking mechanism.
;; 4. Macros & fxns operating in non-user or root context can access all the
;; data, to handle the inter-user cases of ownership transitions,
;; modifications, application specific locking, complex sharing patterns,
;; and so forth. This strongly enforces a layering in programs, where any
;; dangerous inter-user code is all found in this one small place.
;; 5. The above is made more complex in that some users administrate groups
;; of other users, so their runtime should scope data to their group, and
;; tag their personal ownership vs. group. Possibly this is simplified by
;; unifying users & groups (wherein any user may be a tree of permissions)
;;
;; I did some research, looking for any languages that have similar features
;; already. I have found none so far; any attention paid to the basic idea
;; is devoted to instantiation ("isolate users with threads") or connection
;; ("use an object broker"). So I don't have a code comparison; in my mind
;; code looks similar, except the new language would lack mutexes and
;; permissions checking in 99% of the code.
;;
;; As an aside, having MVCC (wherein writers never block readers and
;; vice-versa) in the language runtime could be a major boon to both speed
;; and simplicity: it is perhaps a primary reason that so many DB-backed
;; multi-user web applications have been successfully built by people who
;; have never heard the term 'canonical resource ordering'. There are times
;; when you need a more complex or ruthless lock, but 99% of the time MVCC is
;; what you want. Using MVCC in the background could be very resource
;; intensive, but as it assures that there is no blocking on reads, the total
;; use on the wall clock is much lower, possibly allowing more users per
;; processor (a key metric for a language focused on server apps). Also,
;; since lock contention on multiple intersecting users performing a variety
;; of actions is still one of the most difficult debugging problems around,
;; this could be an extremely powerful feature for simplicity.
;;
;; I discussed this idea with friends, most of whom didn't see the gain in
;; making a language over making a library in Java or its ilk, except for my
;; claims of terseness and the need to alter the runtime. I *was* made to
;; see that there is nothing in my design that could not be generalized to
;; other uses, but I think having an explicit pronoun for the user construct
;; makes the whole design much more immediate and valuable.
;;
;;
;;
;; *** Will Duquette: Tcl
;;
;;
;; I was browsing your site, and happened to read the article on the
;; history of T. In that article, the author mentions an early
;; Scheme program called "markup". markup took as input files containing
;; plain text with Scheme code embedded in curly braces, executed the
;; Scheme code, and (presumably) wrote the result to the output along
;; with the plain text.
;;
;; I was intrigued by this, because I'm the author of a similar program
;; based on Tcl rather than Scheme (see http://www.wjduquette.com/expand)
;; if you're at all interested. And when I was experimenting with Common
;; Lisp recently I considered writing such a thing in Common Lisp.
;; Eventually I rejected the idea, and the reason was a nifty if
;; obscure feature of Tcl that I didn't find in CL (or perhaps I just
;; missed it). You might want to provide in Arc.
;;
;; Tcl has an interactive shell. If you type something that's obviously
;; a partial command, it displays a secondary prompt and allows you to
;; keep typing for as many lines as you need. When it detects that you've
;; entered a full command, it executes it. In Lisp terms, this means that
;; Tcl can take an arbitrary string and determine whether it is a complete
;; S-expression or not, taking into account all the nasty cases, such
;; as mismatched parentheses in embedded text strings.
;;
;; Now obviously a Lisp shell can do the same thing. Where Tcl possibly
;; differs is that there is a standard Tcl command, "info complete". If
;; variable "mightBeComplete" contains some text, I can write code like this:
;;
;; if {[info complete $mightBeComplete]} {
;; # Execute the code in mightBeComplete
;; }
;;
;; Now, consider the markup program again. It's going to read text from the
;; file, looking for the first (non-escaped?) left curly bracket. Then it's
;; going to look for the matching right curly bracket, and execute the code
;; in between. But unless it forbids right curly brackets to appear in
;; the embedded Scheme code, it can't just scan for the next right curly
;; bracket; it has to find the first right curly bracket that follows
;; a complete S-expression (or perhaps a sequence of them). And that
;; essentially implies parsing the embedded Scheme code.
;;
;; In Tcl, I don't need to do that. I search for the next close brace,
;; and ask Tcl whether the intervening text is a complete command. If it
;; is, I execute it; otherwise, I step onward to the next close brace
;; and so forth.
;;
;; You're targetting Arc to the server side of things, and this kind of
;; easy code embedding might be very useful.
;;
;; I also note that Tcl has a "subst" command, which lets you explicitly
;; ask for variable and command interpolation into a string. My "expand"
;; tool could have been implemented so that it simply read in the entire
;; file of text and let "subst" do its thing. In this case, I wouldn't
;; scan the file at all. But "subst" does its job all at once; it develops
;; that at times it's useful to process the input sequentially. For
;; example, consider this input text:
;;
;; Some text [capitalize]with embedded markup[/capitalize].
;;
;; Because "expand" processes the input sequentially, I can make the
;; "capitalize" tag begin to capture the input text. Then, the
;; "/capitalize" tag can retrieve the input received since
;; "capitalize" and convert it all to upper case. Tcl's "subst"
;; command doesn't allow for that kind of manipulation.
;;
;;
;;
;; *** Rene De Visser: CL Lacks
;;
;;
;; 1) Immutabile vs mutible
;;
;; In my lisp programs I find myself often deciding whether a particular data
;; structure, will for the purpose of the program be:
;;
;; Immutable:
;;
;; In this case the data structure will be shared through all parts of the
;; program, and if any part of the program wants a changed version of the
;; datastructure it must copy it, creating a modified new data structure (so as
;; not to cause wrong side-effects in the rest of the program).
;;
;; Mutable:
;;
;; The data structure represents a single thing that changes. It should not be
;; copied, but changed directly.
;;
;; In common lisp data structures are not tagged as mutable or immutable so the
;; above can not happen automatically. One must be extremely carefull to track
;; which data structure falls into which category. A single error can lead to
;; subtle problems in another part of the program.
;;
;; It also leads to the fact that most operaters in common lisp there are two
;; versions. One which copies and one which modifies destructively.
;;
;; Also Immutable / Mutable is related to equality and so without data being
;; tagged as mutable or immutable it is not possible to have a correct equality
;; check (resulting in multiple equality operations in CL which still have
;; problems) and no deep copy.
;;
;; 2) Data structure representation.
;;
;; Using STL in C++ one can change the container representation used, for
;; example from unsorted list, to sorted list, to red/black tree without
;; changing any code in the rest of the program.
;;
;; In Lisp, perhaps you are using lists to represent sets, however some of
;; these sets are small, an so an unsort list is best, others need to be used
;; in a sort manner and others are very large and need to be kept in a
;; red/black tree as sets with 1000000 items don't behave very well otherwise.
;;
;; in Lisp each set (list) needs to be handle with different client code. Again
;; any mistake (for example resulting from change in representation, or mixing
;; up representations) results in subtle errors.
;;
;; Basically lisp needs a 'SET' data type in order to separate the
;; representaton of a SET from the use of it.
;;
;; More broadly this could be interpreted that LISP needs more abstract
;; functions (as in the STL) which don't care about the underlying data
;; abstract.
;;
;; This is to a degree supported by the sequence concept in CL, but in practice
;; this can't even cope with the SET problem above.
;;
;;
;;
;; *** J Storrs Hall: Semantic Incoherency
;;
;; I consider one of the worst semantic incoherencies of
;; Common Lisp the incompatibility between "functions" defined
;; as macros and the "functional programming" features. Both are
;; higher-order concepts but each seems to be designed without
;; any consideration of the other.
;;
;;
;;
;; *** Michael Vanier: LFSPs
;;
;; My Ph.D. research involved writing very complex simulations of nervous
;; systems (real "neural networks", not the sorta-AI kind). I used a
;; simulation package that was written in C and had its own (horrible,
;; ghastly) scripting language, all written in-house. I extended the hell out
;; of it, but the experience was so painful I don't think I can ever work on a
;; large C project again. Since I want to continue working in this field, and
;; since I love to hack, I want to re-write the simulator "the right way".
;; However, I've been dithering on the choice of language. It's pretty clear
;; that the core simulation objects have to be written in C++. C is too
;; painful, and anything else is going to give an unacceptable hit in speed
;; (simulation is one of those rare fields where it is impossible to have too
;; much speed). But this is probably less than 50% of the code, maybe much
;; less. The rest is infrastructure; scripting interface as well as a lot of
;; support code. For scripting I want to use scheme or some lisp dialect.
;; But the language choice for infrastructure is unclear. I could use C++,
;; but that's unnecessarily painful especially since the infrastructure is not
;; speed-critical. So I'd decided to use java; it's fast enough, there are a
;; lot of libraries, and a lot of people know it so I could conceivably get
;; others to work on it as well. After making this decision, my interest
;; waned and I started another (unrelated) project.
;;
;; In the process of working on that other project (which involves scheme and
;; Objective Caml (ocaml), an ML dialect), it occurred to me that ocaml would
;; be a better choice than java for the intermediate layer. It's faster, has
;; better type-checking, is much more powerful, and can even be used as its
;; own scripting language because of the type inference and interactive REPL.
;; If necessary, I could write a simple lisp-like language on top of ocaml
;; with little difficulty. The C interface to ocaml is also quite mature, and
;; there is a good-sized standard library (though nothing like the enormous
;; java libraries). Also, it's much lighter weight than java. But here is
;; the most important reason: it's a hell of a lot more fun to program in than
;; java. Writing java code, though not particulary painful in the sense that
;; C is painful (core dumps etc.), puts me to sleep. Writing ocaml (which is
;; a "language designed for smart people" if there ever was one) is exciting.
;; My motivation to tackle the project has tripled overnight. The interesting
;; question is: why is ocaml so much more fun than java? Why are "languages
;; designed for smart people" (LFSPs) so much more fun to program in than
;; "languages designed for the masses" (LFMs)?
;;
;; One possibility is that LFSPs tend to be more unusual, and hence are more
;; novel. I'll admit that this is part of the answer, but it misses the main
;; point. *Any* new language is going to be novel, but the novelty usually
;; wears off quickly. The real point is that LFSPs have a much greater
;; support for abstraction, and in particular for defining your *own*
;; abstractions, than LFMs. This is not accidental; LFMs *deliberately*
;; restrict the abstractive power of the language, because of the feeling that
;; users "can't handle" that much power. This means that there is a glass
;; ceiling of abstraction; your designs can only get this abstract and no
;; more. This is reassuring to Joe Average, because he knows that he isn't
;; going to see any code he can't understand. It is reassuring to Joe Boss,
;; because he knows that he can always fire you and hire another programmer to
;; maintain and extend your code. But it is incredibly frustrating to Joe
;; Wizard Hacker, because he knows that his design can be made N times more
;; general and more abstract but the language forces him to do the Same Old
;; Thing again and again. This grinds you down after a while; if I had a
;; nickel for every time I've written "for (i = 0; i < N; i++)" in C I'd be a
;; millionaire. I've known several programmers who after only a few years of
;; hardcore hacking get burned out to the point where they say they never want
;; to code again. This is really tragic, and I think part of it is that
;; they're using LFMs when they should be using LFSPs. I note with some
;; interest that the original Smalltalk designers are *still* writing code in
;; Smalltalk; the Squeak project was founded by them and is mainly maintained
;; by them. I'm not sure if Smalltalk was intended to be a LFSP (actually,
;; I'm pretty sure it wasn't), but it does have good abstractive power and
;; does scare off newcomers, so I guess it is one :-)
;;
;; So the bottom line is: computer languages designed for smart people don't
;; just liberate the language designer, they liberate the programmer as well.
;;
;;
;;
;; *** Peter Norvig: Syntax
;;
;; Some comments:
;;
;; * car and cdr are warts; why not hd and tl?
;;
;; * If Unix won, then the symbol red should be red, not RED
;;
;; * For the Scheme I wrote for Junglee's next-generation wrapper language, I
;; allowed three abbreviations: (1) If a non-alphanumeric symbol appeared in
;; the first or second element of a list to be evaled, then the list is in
;; infix form. So (x = 3 + 4) is (= x (+ 3 4)), and
;; (- x * y) is (* (- x) y). And (2), if a symbol is delimited by a "(", then
;; it moves inside the list. So f(a b) is (f a b), while f (a b) is two
;; s-exps. And (3), commas are removed from the list after infix parsing is
;; done, but serve as barriers to infix beforehand, so f(a, b) is (f a b),
;; while in f(-a, b + c), each of -a and b + c gets infix-parsed separatly, and
;; then they get put together as (f (- a) (+ b c)). This seemed to satisfy the
;; infix advocates (and annoy some of the Scheme purists). You might consider
;; something like this.
;;
;; * Non-chars in strings doesn't make sense to me; I always think of strings
;; as arrays of type char; the tricky issues are whether strings are mutable,
;; and if so, extensible, and if they're mutable, which operations are
;; efficient (i.e. should removing the first char be O(1) or O(n)). The other
;; issue is which library functions should only work on strings, and which work
;; on arrays or sequences. Finally, you need an extensible protocol for
;; sequences (like Dylan, and in-the-works in Python).
;;
;; * If you have (do (= x val) ...) then you don't need let and with.
;;
;; * My inclination would be to have ds, opt and get be non-alphabetics, e.g.
;; (def f (a (: (b c)) (? d 4) (& e f)) ...)
;; This way its easier to see what's a param and what isn't.
;;
;;
;;
;; *** Peter Norvig: Another Onion
;;
;; I think conflating pairs and lists is an onion that accounts for several
;; pages worth of equivocation in ANSI CL. Both pairs (lightweight structures
;; that can hold two components) and lists (hold arbitrary number of components
;; with O(n) acces time) are useful ideas, but Lisp uses a cons cell for both
;; for two reasons: (1) at the time, data abstraction was not in vogue, and (2)
;; if you've only got 2 bits of tags, you want to be parsimonious with your
;; basic types. But conflating the two means that every function that takes a
;; list must specify what it does when passed an improper list. If it were my
;; language, (cons x y) would raise an exception if y is not a list, and I'd
;; consider whether to separately have (pair x y), which would be accessed with
;; first and second, not first and rest, or whether to just use (array x y).
;; If you do have pair as a subclass of array, you might also want to consider
;; triplet.
;;
;; As for (+ "foo" "bar"), I'm somewhat against it, because it means (a) + is
;; no longer commutative, and (b), no longer associative: compare (+ (+ 2 3)
;; "four") and (+ 2 (+ 3 "four")). I've actually seen errors of the second
;; kind in Java programs: sys.out.println("answer = " + x + y) instead of
;; ("answer =" + (x + y)). On the other hand, I admit, after using Python,
;; that "foo" + "bar" feels natural, to the extent that I wasted 20 minutes
;; debugging a Perl program where I used + instead of . for string
;; concatenation. Whatever you decide about the operator (I'm thinking I'd
;; rather write "foo" & "bar"), I recommend NOT having an automatic coercion
;; from object to string; I think Python is right in raising an error for this.
;; In Perl its even worse, because my strings were coerced to numbers (0).
;;
;;
;;
;; *** Michael Vanier: OO
;;
;; I think one thing that lisp really needs that C and C++ have is the ability
;; to lay out data types in a very low-level fashion. This is not something
;; that should be done lightly and perhaps not at all unless you are a very
;; experienced programmer, but it's critical to getting really good
;; performance in many cases. I suspect the reason why lisps don't have it is
;; that it can interact in hairy ways with the garbage collection scheme,
;; which makes life much harder than it is in C/C++. There are also issues of
;; array bounds non-checking etc. and then before you know it all safety bets
;; are off.
;;
;; This leads naturally to the idea of having a "low-level lisp" in which such
;; programs can be written and then used safely by the standard lisp. I
;; believe this is how prescheme/scheme48 worked (works?), although this was
;; done just to bootstrap the system AFAICT. There is also an analogy to C#
;; and Modula-3 (garbage collected languages that allow for "unsafe modules").
;; I would really like it if Arc offered some facility like this, but I don't
;; understand the issues well enough to know if it's feasible or not.
;;
;;
;;
;; *** Matthias Felleisen: OO
;;
;; Paul, you don't have to go to bunches of bytes and do things atop.
;;
;; In PLT Scheme v200 everything is a struct, yet these values won't respond
;; with #t to struct? because we don't want anyone to think of these things as
;; structs.
;;
;; Also, we are currently designing extensions so that programmers can define
;; functions and ask the environment to treat them as primitives, especially
;; with respect to soft typing. So you will say something like
;;
;; (: f (number -> number))
;; (define (f x) ... (+ x ...) ...)
;;
;; and f is treated as a new "primitive". If the soft typer sees that you
;; misapply it somewhere, it will be hi-lited in red. It's up to you to think
;; of this as a typer and you will refrain from running this code, or you may
;; decide that the type system is too conservative and you run the code
;; anyway, knowing that we enforce the types anyway.
;;
;; The key is not just to write the types down. You need to analyze and
;; enforce them. And in "Lisp" (or Perl or Python or Curl) the question is how
;; to scale this to higher-order types.
;;
;; Even more general: we have known fro 50 years how to build a language atop
;; bunches of bytes. PL design will make progress if we do the exact same
;; thing but without ever thinking what is inside the machine. Computations
;; are about value manipulations. At the moment, we represent values in bits
;; and bytes, but why think about those. It just pollutes program design.
;;
;;
;;
;; *** Mike Thomas: Squeak
;;
;; - I think that an interesting way to test language ideas is the development
;; model used for Squeak (Smalltalk dialect) - anyone, even raw beginners, can
;; add anything they like and stuff which is popular survives simply because it
;; is used. (Survival of the fittest.)
;;
;; - I like the work being done on region based memory management eg: MLKit at
;; the University of Copenhagen, and a C dialect from Lucent technologies (name
;; escapes me).
;;
;; - Coherent FFI from the beginning and an IDL compiler targeted at ARC to
;; allow ease of interfacing to OS and third party libraries. Glasgow Haskell
;; compiler has successfully used this strategy.
;;
;; - incorporate type inferencing and optional type hints.
;;
;; I make these comments from the point of view of a person who leans to the
;; Haskell/SML side of programming with fond memories of Scheme (apart from the
;; fact that my bread and butter is obtained from the C family), with a
;; background in mathematical, game, GIS and large oil industry technical
;; software development.
;;
;;
;;
;; *** Jecel Assumpcao: Objects
;;
;; There is a lot of good advice in your website but you don't seem to be
;; following it regarding objects: don't put in stuff for others to use or
;; to be politically correct. If you don't like them yourself, just leave
;; them out.
;;
;; My own languages have always been OO and I think objects really help in
;; any non trivial program, but each person has his own preferences. There
;; are several different styles of object systems and I think that the
;; kind in E or Beta might be a better fit for Arc and might be more
;; useful to you.
;;
;; Let's do the classical cartesian point example. My first try will avoid
;; adding syntax at the cost of making most expressions look infix or even
;; postfix. A list (c x y z), where c is a closure, has the same effect as
;; evaluating (x y z) in c's context. And make-closure returns the value
;; of the current execution context.
;;
;; (define point (x y)
;; ((define + (p) (point (x + (p x)) (y + (p y))))
;; (define pr () (("point " pr) (x pr) (" " pr) (y pr)))
;; (make-closure)
;; ))
;;
;; (((point 3 4) + (point 5 6)) pr)
;;
;; The reason why the "+" ended up as an infix operator was that it had to
;; be preceded by a context (object) so that the normal "+" wouldn't be
;; invoked. Note that strings and numbers also were treated as closures in
;; the code above.
;;
;; This is not very Lisp-like, so I will add the following syntax element:
;; a ":" will indicate that the element following it is the context in
;; which the surrounding expression should be evaluated:
;;
;; (define point (x y)
;; ((define + (self p) (point (+ :x (:p x)) (+ :y (:p y))))
;; (define pr (self) ((pr :"point ") (pr :x) (pr :" ") (pr :y)))
;; (make-closure)
;; ))
;;
;; (pr :(+ :(point 3 4) (point 5 6)))
;;
;; Well, it is still ugly but at least it is starting to look like Lisp.
;; The idea is to use a few general constructs instead of a lot of
;; specialized ones. For example, using functions as "classes" has the
;; nice side effect of us not having to do anything extra to get a single
;; inheritance-like functionality - lexical scoping will do just fine.
;;
;; With the above notation, you don't have to dispatch on the first
;; argument (your cons complaint). The "+" would have to be rewritten in a
;; more symetrical form before we could have (pr :(+ (point 3 4) :(point 5
;; 6))) however:
;;
;; (define + (a b) (point (+ :(:a x) (:b x)) (+ :(:a y) (:b y))))
;;
;; All those (:b x) are very ugly and should be simplified along the lines
;; of your ("hello" 2). This isn't really a solution, but just a general
;; direction that I feel could be followed.
;;
;; If objects are convenient enough, I don't think you will the the
;; database types.
;;
;; While "fn" is cleaner than "lambda", I would rather use "?" since it
;; isn't harder to type and stands out better in the code. It is also
;; mnemonic for "mystery function" ;-)
;;
;;
;; *** John McClave: End Test
;;
;; I am interested in the 'given'
;; overhead of the pervasive end loop test and its
;; possible elimination. First a hardware analogy.
;; Is it possible to use a hardware settable interrupt
;; to replace the end of loop test and just use
;; unconditional jumps to keep the loop runnable.
;; In Lisp-like coding where end of list tests are part
;; of most recursive function definitions is it possible
;; to preclude this overhead by some form of latent
;; daemon tagged onto the list structure and some form of
;; unconditional jump. Could a closure of some sort be
;; triggered to end the function process.
;;
;;
;;
;; *** Avi Bryant: Continuations
;;
;; So here's a cool code example for your consideration, very slightly
;; abbreviated:
;;
;; -----------------------------------
;;
;; Object subclass: #Continuation
;; instanceVariableNames: 'stack '
;; classVariableNames: ''
;; poolDictionaries: ''
;; category: 'Kernel-Methods'!
;;
;; !Continuation methodsFor: 'invocation'!
;; value: v
;; thisContext sender: stack copyStack.
;; ^v !!
;;
;; !Continuation class methodsFor: 'instance creation'!
;; fromContext: aStack
;; ^super new stack: aStack copyStack !!
;;
;; !BlockContext methodsFor: 'continuations'!
;; callCC
;; ^self value: (Continuation fromContext: thisContext sender)! !
;;
;; -------------------------------------
;;
;; Of course, it's easy to provide an equivalent example in Scheme - call/cc
;; already exists. But it's completely impossible, as far as I know, to
;; provide an equivalent example in CL, even a really ugly one. I bring it
;; up partly because I know you realize the usefullness of continuations for
;; web development, and yet I haven't seen any mention (did I miss it?) of
;; continuations in Arc. And I know from personal experience that a
;; closure-based continuation-passing style, as it sounds like you adopted
;; for ViaWeb, is useful but far more frustrating and less transparent than
;; true continuations. So, at the very least, let me request that full
;; continuations be included in Arc.
;;
;; But I also bring it up because, to my surprise, I have found myself using
;; Smalltalk rather than Lisp for my web development - although I deplore the
;; lack of macros, in cases like continuations I have found smalltalk *more*
;; powerful than lisp. Say what you like about "everything is an object",
;; the fact that stack frames (and closures) are reified makes certain games
;; much easier. Here's another code snippet:
;;
;; snapshot := self copy.
;; context := thisContext sender.
;; [context isNil] whileFalse:
;; [((context isKindOf: MethodContext) and: [context receiver = self])
;; ifTrue: [context receiver: snapshot].
;; context := context sender].
;;
;; Since using a functional style is all but impossible in smalltalk, this
;; offers an interesting alternative - switching midmethod to a copy of the
;; current object. Invoked right after a call/cc, it ensures that each
;; invocation of that continuation occurs in a separate context of sorts,
;; which is very useful in a browser-back-button world (yes, it's also
;; dangerous and limited, but it's very pragmatic if you know what you're
;; doing - the actual version I use also has various sanity checks that only
;; make sense in the context of my framework).
;;
;; So will we ever see this kind of reflective power in a lisp? Or am I
;; going to have to write a prefix-syntax parser for smalltalk to have my
;; cake and eat it too?
;;
;;
;;
;; *** Seth Gordon: Syntax
;;
;; I have a theory that one reason people get techy about all of Lisp's
;; parentheses is that people's brains have trouble parsing deeply
;; recursive sentences, so when they see a piece of code with deeply
;; nested structures, it looks very intimidating.
;;
;; Therefore, I suggest creating an infix operator ~, defined as:
;;
;; (f ~ g x) ==> (f (g x))
;; (f ~ g x ~ h y) ==> (f (g x (h y)))
;;
;; To pick a piece of Scheme code that comes to hand: this operator would
;; let one represent
;;
;; (define serve
;; ; use default values from configuration.ss by default
;; (opt-lambda ([port port]
;; [virtual-hosts virtual-hosts]
;; [max-waiting max-waiting])
;; (let ([custodian (make-custodian)])
;; (parameterize ([current-custodian custodian])
;; (let ([listener (tcp-listen port max-waiting)])
;; ; If tcp-listen fails, the exception will be raised in the caller's thread.
;; (thread (lambda ()
;; (server-loop custodian listener
;; (make-config virtual-hosts (make-hash-table)
;; (make-hash-table)
;; (make-hash-table)))))))
;; (lambda () (custodian-shutdown-all custodian)))))
;;
;; as
;;
;; (define serve
;; ; use default values from configuration.ss by default
;; ~ opt-lambda ((port port)
;; (virtual-hosts virtual-hosts)
;; (max-waiting max-waiting))
;; ~ let ((custodian (make-custodian)))
;; (parameterize ([current-custodian custodian])
;; ~ let ([listener (tcp-listen port max-waiting)])
;; ; If tcp-listen fails, the exception will be raised in the caller's thread.
;; ~ thread ~ lambda ()
;; ~ server-loop custodian listener
;; ~ make-config virtual-hosts
;; (make-hash-table)
;; (make-hash-table)
;; (make-hash-table))
;; (lambda () ~ custodian-shutdown-all custodian))
;;
;;
;;
;; *** Trevor Blackwell: Modularity
;;
;; It's worth distinguishing a third category of programming
;; environments: one where a solitary hacker uses many open-source
;; modules written by various folks. I consider this a very good
;; environment, unlike pack programming. But it has some requirements in
;; common with it. Various languages succeed or fail dramatically in
;; making this work smoothly.
;;
;; In C/C++, I find I can almost never use other people's stuff
;; conveniently. Most have some annoying requirements for memory
;; management, or use different string types (char *, STL string, GNU
;; String, custom string class), or array/hash types, or streams (FILE *,
;; iostream) or have nasty portability typedefs (int32, Float).
;;
;; CL has fewer such troubles since it has standard memory management &
;; string/hash/array types, but there are often nasty namespace
;; collisions or load order dependencies, especially with macros.
;;
;; Most chunks of CL code I've seen (which are mostly PG's) won't work
;; without special libraries, which have short names and are likely to
;; conflict with other macro libraries or even different versions of the
;; same macro libraries.
;;
;; Perl packages work pretty well, because everyone agrees on how basic
;; types like string, stream, array and hash should work, and the normal
;; use of packages avoids any namespace collisions. I don't think I ever
;; had a open source Perl module break something. I guess Java also
;; prevents conflicts, but you have to give up an awful lot to get it.
;; The huge assortment of open source Perl packages testifies to the ease
;; of writing them. I've taken a few packages that I wrote for my own
;; purpose and found it very easy to make them self-contained and
;; contribute them. Usually, people only write C++ libraries for very
;; large projects, and it requires a different programming style from
;; what you'd use for your own code.
;;
;; Anyway, I suggest that Arc's modularity features should be designed to
;; support use of open-source modules in single-hacker projects, not to
;; support pack programming. This suggests, in addition to what CL
;; already has:
;;
;; - that modularity be a convention (CL, Perl), not something enforced
;; by the compiler (Java). Sadly, I find the CL module system way to
;; cumbersome to actually use. It has to be convenient enough to use in
;; ordinary programming, not a special thing you use when you're writing
;; a module for external use.
;;
;; - there be a sufficient basic library that everyone won't have to
;; write their own basic library. I'm talking about the sort of functions
;; from On Lisp like last1, in, single, append1, conc1, mklist,
;; flatten. If everyone has their own, then you have to package it up
;; with any code you publish (making it awkward to publish) and it'll be
;; hard to read other people's code with different definitions of basic
;; functions.
;;
;;
;;
;; *** Mike Vanier: MATLAB
;;
;; Point 1: Matrix manipulation is a canonical example of something that
;; deserves its own dialect. DO NOT build this in to the core.
;;
;; Point 2: Having matrix functions like eig() for eigenvalues is trivial and
;; can be done in any language if the library exists. So that's not
;; a big deal.
;;
;; Point 3: Syntactically, you need this:
;;
;; a) A nice literal data entry notation for arrays. Matlab's notation is
;; NOT nice because it doesn't scale for 3D+ arrays. What would be
;; better is e.g.
;;
;; my_array = [[[1 2] [3 4]] [[5 6] [7 8]]]
;;
;; This scales nicely. Hey, S-expressions again! :-)
;;
;; b) Functions that operate by default on arrays as opposed to on scalars
;; (or really on both). So, sin(my_array) will compute the sin of all
;; the elements.
;;
;; c) Various functions for manipulating and transforming array shape. In
;; 2D arrays, you have resize() and transpose (written ' in matlab), but
;; these can be generalized.
;;
;; d) [Hard!] Higher-order functions to specify the "rank" of a function
;; call. In simple terms, this refers to which axes of the array are
;; used in the computation. For instance, the sum() function applied to
;; a 2D array might mean "return the column sums" or "return the row
;; sums".
;;
;; The only language that gets this right that I know of is J
;; (www.jsoftware.com). J is beautifully designed, but I don't like the
;; line-noise syntax. If Arc had a dialect that could handle this material as
;; elegantly, I would use it. Also, J is closed-source (but free), yadda
;; yadda (the Rebol/Curl syndrome).
;;
;; Look at the J documentation; it's all available for download. Quite
;; mind-stretching. Aside from scalar data types (characters and several
;; types of numbers) the only data types are multidimensional arrays which
;; hold a uniform data type and "boxed arrays" (which are arrays that can hold
;; arbitrary data types, including other arrays). Very neat stuff.
;;
;;
;;
;; *** Neil Conway: Ruby
;;
;; 1) Blocks: 90% of the benefit of functional programming, no weird
;; academic ML-type stuff ;-)
;;
;; ary = [1,2,3]
;; ary.each do |element|
;; puts "Item: #{element}"
;; end
;;
;; 2) Everything is an object:
;;
;; 5.times do
;; puts "hello, world"
;; end
;;
;; 3) Dynamic class definitions and singleton method definitions:
;;
;; class Foo
;; def bar
;; "bar"
;; end
;; end
;;
;; f = Foo.new
;; f.bar
;; => "bar"
;;
;; # add more definitions to Foo
;; class Foo
;; def baz
;; "baz"
;; end
;; end
;;
;; f.baz
;; => "baz"
;;
;; def f.another_method
;; "Singleton"
;; end
;;
;; f.another_method
;; => "Singleton"
;;
;; Foo.new.another_method
;; => error, no such method
;;
;; (you can also add definitions to built-in classes like String and Array
;; like this -- making it a convenient place to store utility functions)
;;
;; 4) Built-in design patterns: (or rather, a mixin implementation that is
;; flexible enough to support this kinds of patterns very naturally)
;;
;; require 'singleton'
;;
;; class FooS
;; include Singleton #mixin the Singleton module
;;
;; def initialize
;; puts "FooS init"
;; end
;;
;; def bar
;; "bar"
;; end
;; end
;;
;; f = FooS.new
;; => error, 'new' is private
;; f1 = FooS.instance
;; # "FooS init" printed to screen
;; f2 = FooS.instance
;;
;; f1.inspect
;; => #
;;
;; f2.inspect
;; => #
;;
;; If you plan to draw any language features from Python for the design of
;; Arc, I'd also suggest looking carefully at Ruby: IMHO, it offers all of
;; Python's features with a more elegant design, as well as a number of
;; very interesting features from languages like Smalltalk.
;;
;;
;;
;; *** Olin Shivers: Regexps
;;
;; If you provide regexps, then you should feel a moral obligation
;; to also provide context-free grammars, i.e., a parser tool, as
;; well. It's a big problem that languages that provide cheap, easy
;; regexp matching encourage programmers to use regexps to analyse
;; things that are *not* regular languages. Oops. So you get heuristic
;; code that works... most of the time. Perl is the classic example.
;;
;; If you steal Manuel Serrano's little built-in, lightweight grammar
;; language, then people can use regexps to recognise regular languages
;; and CFGs to recognise more complex things.
;;
;;
;;
;; *** Pinku Surana: Brevity
;;
;; - Check out Todd Proebsting's TR on "Programming Shorthands". It's about
;; "pronouns" in PL syntax.
;; http://www.research.microsoft.com/~toddpro/
;;
;; - Syntactically, Haskell bested ML's "fn" for lambda:
;; Haskell: \x -> x + 1
;; ML: fn x => x + 1
;; Scheme: (lambda (x) (+ x 1))
;;
;; - Haskell treats strings as lists of characters. You might find their
;; experience interesting.
;;
;; - pattern matching syntax for lists is short & concise.
;;
;; - List comprehensions (syntax within []'s below) can do powerful things with
;; brief syntax:
;; quicksort [] = []
;; quicksort (x:xs) = quicksort [y | y <- xs, y=x]
;;
;; An equivalent Scheme program:
;; (define (quicksort lst)
;; (if (null? lst)
;; lst
;; (let ((x (car lst)) (xs (cdr lst)))
;; (append (quicksort (filter (lambda (y) (< y x)) xs)
;; (list x)
;; (quicksort (filter (lambda (y) (>= y x)) xs)))))
;;
;;
;;
;; *** Kragen Sitaker: Comments on Arc
;;
;; fn
;; ----
;;
;; Since setf plays such a prominent role in Arc, there should be a
;; version of fn that allows you to define a 'setter' function as well as
;; a getter.
;;
;; Compound = Functions on Indices
;; -------------------------------
;;
;; I wish every language used the same form for function call, hash
;; fetches, and array indexing, the way arc does. It's a brilliant idea.
;;
;; In order to be able to write new compound data types in Arc, there
;; needs to be a way to create values that can be called as functions and
;; also implement other operations. This can be done in a
;; straightforward way with the overloading system described for objects
;; in "Arc at 3 Weeks": overload apply. (Apply should probably be called
;; "call", if we're rebuilding Lisp from the ground up.)
;;
;; Pronouns
;; --------
;;
;; 'it' being bound by iteration and conditionals is also a brilliant
;; idea. Python is working toward getting something similar, but
;; nobody's done it yet. FORTH has sort of had it with DO and I and J
;; for a while, but not in conditionals. (One might argue that FORTH is
;; almost all pronouns; very little data is named.) And, of course, Perl
;; is full of pronouns: <>, $_, the current filehandle, etc.
;;
;; Shouldn't there be a form of 'each' and 'to' that bind a pronoun, too,
;; as in Perl and FORTH?
;;
;; (each '(a b c) (pr item))
;; (to 10 (= (ary i) (* i i)))
;;
;; >From the examples, it looks like 'keep' gives a way to write a list
;; comprehension, and 'sum' gives a way to write foldl (+) (APL's +/)
;; over a list comprehension; except, of course, you can write "list
;; comprehensions" that iterate over non-list-like things. Some other
;; languages (Python, for example) are handling this by making almost
;; anything you can iterate over look like a list; list comprehensions
;; are nice, compact, and readable.
;;
;; DBs
;; ----
;;
;; The proposed semantics for fetching from a DB are that nonexistent
;; keys return the current value of the global variable *fail*, which
;; defaults to nil. This is wrong, for two reasons:
;;
;; - If mydb is a DB that doesn't have any false values in it, and nil is
;; false, this code will almost always work, but it's broken:
;;
;; (if (mydb foo) (x it) (y))
;;
;; because it assumes that *fail* is set to something in particular. A
;; correct variant of this code (assuming = can set a global variable) is
;;
;; (do (= *fail* nil) (if (mydb foo) (x it) (y)))
;;
;; To write correct code, you'll almost always have to set *fail* like
;; this before a test for existence, because you must ensure it's set to
;; something you know can't legitimately be in the DB.
;;
;; Making correct code be much more verbose than incorrect code that
;; almost always works, but breaks when a completely unrelated part of
;; the program changes, is probably a bad idea. (I know Graham is
;; designing a language for good programmers, who will presumably take
;; the extra time to write the correct form, but I think that's going a
;; little too far.)
;;
;; - there's a much weaker reason, which is that *fail* might actually be
;; the value of an item in a DB --- for example, a DB that contained the
;; program's global variables.
;;
;; I like Python's approach to this problem. Fetching a nonexistent
;; value in the normal way will raise an exception, which is usually the
;; right thing. So you could write the above code as
;;
;; (try (x (mydb foo)) 'KeyError (y))
;;
;; But there is also an operation 'get', which returns a specified
;; default value if the requested key doesn't exist, and is *much*
;; briefer than the corresponding operation with *fail*; compare:
;;
;; (do (= *fail* "") (mydb foo))
;; (get mydb foo "")
;; or even
;; (mydb foo "")
;;
;; and an operation 'has_key', which allows the operation to be written as:
;;
;; (if (has_key mydb foo) (x (mydb foo)) (y))
;;
;; although this is nearly as verbose as the correct version with *fail*.
;;
;; Another approach: The two-argument variant could actually be a macro
;; (since macros are first-class objects, your DB can be a macro) which
;; evaluates and returns its second argument only if the lookup fails.
;; This almost works to shorten the example above to (x (mydb foo (y))),
;; but that calls x even if the lookup fails.
;;
;; A third approach: has_key is an instance of a wider concept of
;; 'exists'; in Perl, 'exists' applies only to hash lookups, but it
;; applies to a wide variety of operations, essentially everything it
;; makes sense to call setf on.
;;
;; (exists var)
;; (exists (sqrt -1))
;; (exists (mydb 'bob))
;; (exists (car list-or-nil))
;;
;; Python has a fourth generic operation as well: deletion. You might
;; want to check to see whether (foo 1) exists, get its value, set its
;; value, or delete it, regardless of whether foo is a vector, an
;; associative array, or even possibly something else altogether.
;;
;; A fourth approach: in Icon (and, sort of, in Prolog, and, in another
;; way, sort of, in Lisp), expressions can return any number of values,
;; including none; no value returned is boolean false. If a dictionary
;; lookup returns no values if it fails, then
;;
;; (if (mydb foo) (x it) (y))
;;
;; can be correct, because 'no value' is distinct from any particular
;; value, even nil, just as the empty string is distinct from any
;; particular character, even NUL.
;;
;; Lisp's assoc family takes another approach: return something
;; containing the correct value, not the value itself. I don't like
;; this; although pattern-matching could make it less painful to use, I
;; don't think it could provide any better syntax than the 'try' approach
;; above.
;;
;; The default of being indexed by 'eq' is not very good for string
;; processing, unless you use string->symbol a lot --- which might be a
;; good idea for string processing, but will certainly make your code
;; more verbose.
;;
;; If you want the option of using arbitrary equality operators for DBs,
;; and you want some DBs to be hash tables, there needs to be a way of
;; associating a hash with an equality operator.
;;
;; assignment
;; ----------
;;
;; The current proposal for the language has (= var form) either declare
;; a new lexical variable valid until the end of the current block, or
;; change the value of an existing variable.
;;
;; I really prefer languages that have different forms for declaring a
;; local variable (with an initial value) and changing an existing
;; variable; this is one of Python's big deficiencies. I care for the
;; following three reasons:
;; - I can see immediately whether a piece of code uses assignment; I
;; avoid assignment in some parts of my code for testability
;; - the difference between modifying variables declared in a larger
;; scope and shadowing them with local variables with the same names is
;; obvious, and there's an obvious way to do both
;; - misspelled variable names get detected instead of silently producing
;; incorrect results (or occasional run-time errors)
;;
;; I do like the way C++ lets you declare a variable in the scope "the
;; rest of the block", and I think the Scheme/Lisp/C way leads to
;; unreadably-indented code or variables being declared too far from
;; their use.
;;
;; Syntax
;; ------
;;
;; There is another argument for having syntax, other than that it makes
;; programs shorter: it can make programs more readable (in the sense
;; that source code generally is more readable than bytecode, or
;; mathematical formulas are generally more readable than English
;; sentences describing the same formula). In other words, it makes the
;; language more accessible to anyone, good programmers included. I
;; don't think of decompiling bytecode as "dumbing down".
;;
;; Unicode offers a plethora of punctuation; perhaps tasteful and
;; restrained use of some of this punctuation could make the syntax more
;; readable than any possible ASCII syntax. For example, I'd be inclined
;; to write infix bitwise Boolean operators with real Boolean operators
;; instead of ASCII stand-ins, and I'd be inclined to declare variables
;; with some conspicuous piece of punctuation. (In ASCII, I'd probably
;; prefer := if it didn't already have so many closely-related meanings
;; in other languages (Pascal, GNU make).)
;;
;; Implicit progn
;; --------------
;;
;; Graham is right on the mark here; eliminating implicit progn means we
;; can eliminate many of the uglier and more verbose pieces of Lisp
;; syntax.
;;
;; (Implicit progn seems to have crept into the 'to' syntax, though; one
;; of Graham's examples is (to x 5 (sum x) (pr x)).)
;;
;; Pattern matching
;; ----------------
;;
;; Destructuring arguments are very good. I'd like to have full ML-style
;; pattern matching, though; it's possible to write that as a macro, but
;; I'd like it to be part of the language.
;;
;; Recursion on strings
;; --------------------
;;
;; Recursing on strings can be very efficient if the strings are allowed
;; to share structure the way lists do and your compiler is smart enough
;; to reuse storage that can be statically proven garbage. (Or even if
;; it can allocate it on the stack.)
;;
;; Canonical symbol case
;; ---------------------
;;
;; The "Arc at 3 Weeks" paper's examples show symbols being canonicalized
;; into upper case. I don't like this; upper-case is hard to read. I
;; assume it's an artifact of the first Arc implementation running in an
;; existing Common Lisp system.
;;
;; Unicode makes canonical case impractical, anyway, because case-mapping
;; is very complicated.
;;
;; Classes
;; -------
;;
;; The proposed overloading semantics won't give an extensible numeric
;; system.
;;
;; My tastes in object systems appear to be markedly different from
;; Graham's; mine are largely founded in experience with Python. So the
;; object system I want is probably not something he wants:
;;
;; Classes, like compounds, should be called to instantiate objects; this
;; makes the calling code shorter, and also allows you to turn classes
;; into factory functions and vice versa without changing the calling
;; code.
;;
;; There doesn't seem to be a provision for a constructor or methods
;; (other than overloads of existing functions). There probably should
;; be.
;;
;; Class instances should not be callable unless they overload apply, for
;; the following reasons:
;; - there's no need to have one syntax for functions the objects
;; overload and another syntax for getting attributes of the objects.
;; After I say (= pt (class nil 'x 0 'y 0)) (= p1 (pt)), I should be
;; able to ask for (x pt). This does have the disadvantage that "class"
;; must somehow bind x and y in my calling environment if they aren't
;; already bound; I think that's easily accomplished with a macro.
;; (This also removes the necessity for quoting x and y.) (Hmm, what if
;; x is bound to nil? Should we then make nil
;; callable? Perhaps we should just raise an error if x is bound in the
;; local environment, and require that it be quoted or otherwise marked
;; when it's defined as a method in this manner. Quoted attributes
;; would define functions in your local environment which sent
;; doesNotUnderstand to the object passed as their argument, and then
;; overload those functions for this particular object type.)
;; - the current example (p1 'x) prevents p1 from being able to act like
;; some other kind of compound.
;;
;; Most dynamic object systems let you get an object of a class you've
;; never heard of and invoke the correct methods on it. Doing this with
;; the object system described above requires that you have some variable
;; bound to the method "x" defined in "pt" above. I thought this was a
;; problem at first, but I don't think it is now; presumably if your code
;; was written without knowledge of that "x", it won't mention "x" (at
;; least, not meaning that method), and if it was written with knowledge
;; of that "x", it's presumably because there's an interface somewhere
;; that defines "x" to mean something. That interface can be defined in
;; some module somewhere that both "pt" and my calling code import, in a
;; form like this:
;;
;; (defmethods 'x 'y)
;;
;; This has the advantage, not shared by most dynamic object systems,
;; that we can have many methods named "x" without conflict, and we can
;; be sure that the "x" we're calling is intended to implement the
;; interface we expect it to, not some other interface that has a method
;; called "x".
;;
;; Like others, I haven't yet found a compelling use for multiple
;; inheritance, and there are compelling reasons against it.
;;
;; No doc strings
;; --------------
;;
;; No elisp/Python-style documentation strings are mentioned. I want
;; these.
;;
;;
;;
;; *** Miles Egan: Generators
;;
;; The idea is to provide an abstract & extensible iteration interface for
;; collections. This makes it easy to write code that works with any collection
;; and to define new collection types that work with existing code. A brief
;; example:
;;
;; class Series
;; def each
;; for i in 1..3
;; yield i
;; end
;; end
;; end
;;
;; class Words
;; def each
;; for i in ["one", "two", "three"]
;; yield i
;; end
;; end
;; end
;;
;; Series.new.each { |i| puts i * 2 }
;; Words.new.each { |i| puts i * 2 }
;;
;; would output:
;; 2
;; 4
;; 6
;; oneone
;; twotwo
;; threethree
;;
;; I can define a new class that provides an "each" method that returns lines
;; from a file, rows from a database, or widgets from a gui and yield values to
;; the same code block. Alternatively, I can supply arbitrary code blocks to my
;; object's "each" function without coupling the code in the code blocks with the
;; collection's storage implementation. The crucial feature is the "yield"
;; keyword. I don't know of an equally abstract, general, and programmable
;; counterpart in CL.
;;
;;
;; *** Ed Cashin: Things I Want
;;
;; Things that I was very pleased to hear:
;;
;; * arc is UNIX aware!
;;
;; -- languages that acknowledge UNIX are much easier to use for day
;; to day things as well as for big projects.
;;
;; -- they're also easier to learn, since you know a lot of the
;; concepts already (e.g. a socket)
;;
;; * arc knows that I don't want busy work :)
;;
;; -- short but meaningful names
;;
;; -- arc has fewer parentheses when there's no ambiguity
;;
;; * syntax as abbreviation sounds good. I especially like the way
;; syntax can visually mimic data structures (see below).
;;
;; * "it" pronoun is a nice feature
;;
;; * recognition that "do" in common lisp is hard to read. I like the
;; loop constructs in arc so far, except I prefer "times" to "to". I
;; like ruby's syntax:
;;
;; 3.times { print "Ho" }
;;
;; * "keep" and "sum" are very natural and handy looking.
;;
;; Things that worried me:
;;
;; * strings as lists may be nifty, but I want string operations to be
;; lightening fast at runtime.
;;
;; the other could be a "string-list" or something.
;;
;; * when I read that programmers might use indentation to show
;; structure, it worried me that arc might be whitespace dependent
;; like python.
;;
;; I know a lot of good programmers who don't want anything to do
;; with python because it is whitespace dependent.
;;
;; * is the backquote syntax an onion or the best compromise? It's a
;; little weird, but I can't think of anything better.
;;
;; * the "with"/"let" thing ... more simple would be making let do what
;; you have with doing and then forget the one-variable form.
;;
;; * will objects be able to have access controls (e.g. "private")? if
;; not, is that a problem?
;;
;; Things that would be exceptionally nice (literally):
;;
;; * forth-like assembler
;;
;; * easy to use C libraries
;;
;; * easy to make standalone binaries
;;
;; (shared-lib dependency ok, but not external program dependency)
;; (go figure.)
;;
;; * non-buggy, non-experimental native thread support
;;
;; (def do-some-work ()
;; ; ...
;; )
;; (push my-thread-list (thread-new do-some-work))
;;
;; Maybe something like ...
;;
;; (thread-lock 'balance)
;; (= balance (* interest balance))
;; (thread-unlock 'balance)
;;
;; Ruby has nice threads support, but they are really juggled by a
;; single-threaded ruby process. Perl's thread support is still
;; experimental, according to the docs in the latest release.
;;
;; * internationalization
;;
;; -- this seems like a hairy thing, especially with LOCALE
;; environment variables running everywhere, but it might be
;; something to brag about
;;
;; -- maybe unicode support or whatever is in vogue now
;;
;; Things that would be nice (like ruby or perl):
;;
;; * case-sensitive symbols
;;
;; I'm not sure whether this is a win or not, but I was kind of
;; turned off when I first learned that lisp internally thinks of
;; symbols as uppercase ... it reminded me of crippled MS-DOS based
;; filesystems.
;;
;; * syntax for associative data structures
;;
;; makes for visibly obvious initialization. e.g. ruby:
;;
;; keytab["UP"] = "^"
;;
;; keytab = {
;; "LEFT" => "foo",
;; "RIGHT" => "bar",
;; "X" => {
;; "A" => "x a",
;; "B" => "x b",
;; "C" => "x c",
;; }
;; }
;;
;; * excellent regular expression support
;;
;; -- up-to-date fancy stuff like perl's /(\w+?)fancy!/
;;
;; -- must run fast
;;
;; * mixins from ruby are pretty neat
;;
;; -- in C++ and Lisp, there's multiple inheritance; in Java and
;; Objective-C there's single inheritance plus a way to say "and I
;; can also do this and this"
;;
;; in ruby there's a way to "mix in" code too
;;
;; http://www.rubycentral.com/book/tut_modules.html
;;
;; * no dependency on source file names or locations
;;
;; in ruby and lisp namespace/module issues are not related to source
;; code files, which is very convenient, especially compared to the
;; way Java does public classes and package hierarchies based on
;; filename and file location.
;;
;; * adding to the definition of a class after defining it
;;
;; * a way to specify a multi-line section of text in the source
;;
;; both perl and ruby have here documents, where interpolation can be
;; turned on and off. It's very readable and very convenient.
;;
;; * a searchable, browsable web interface to a plethora of arc code
;;
;; comparable to CPAN
;;
;; * a way to do multiple assignment naturally and conveniently
;;
;; e.g., ruby:
;;
;; a, b = 14.divmod 4
;;
;; Some ideas:
;;
;; * Objective-C's method syntax
;;
;; I don't have time to elaborate, but it strikes me as the most
;; readable, self-documenting syntax with the exception of keyword
;; parameters like in lisp.
;;
;; * you could sell the way lisp (and so I'm guessing arc) encompasses
;; the OO model of classical OO languages while providing more.
;;
;; you discuss that in _ANSI Common Lisp_, but I need to reread that
;; chapter, to be honest
;;
;;
;;
;; *** Mikkel Fahn?e J?rgensen: Strings
;;
;; You mention string handling will be important - I agree.
;; Please do not make the mistake of ignoring multiple charactersets.
;; You mention strings may contain non-printable charactes and even character
;; generatingn objects.
;; I think this is a fine concept. And it may go well with multiple
;; charactersets.
;;
;; I had a discussion with Matz who designed the Ruby language. Currently Ruby
;; only supports 8bit characters with a certain level of UTF-8 support.
;; I argued that he should just make it Unicode.
;; But it turns out that a number of popular Asian scripts (language encodings)
;; do not fit well with Unicode.
;; Also, Unicode is not really fixed width, hence the 2-byte representation
;; would sooner or later proove to be incomplete.
;;
;; Matz is currently working on internationalization but I believe his solution
;; would basically be to have a string as a character string with addition type
;; info that stores the encoding. This simple idea is very powerful once you
;; think about it.
;; Conversion between data from old applications to new Unicode charactersets
;; become much easier because the string carried around will tell you what it
;; is, allowing you to do the proper conversion.
;; String concatenation will be require a conversion of at least one of the
;; strings if the types doesn't match. This is like ordinary type coercion.
;;
;; Handling strings as typed instances of an underlying binary stream is a good
;; solution.
;; Different representions can be viewed like different numerical
;; representations (float, double, integer).
;; In this sense the concept of a string as a list works well with multibyte
;; represenations where you cannot easily index a particular character without
;; traversing the entire string.
;;
;; Originally I thought multibyte charactersets were outdated, but now I'm
;; convinced that we just have to be better at dealing with them.
;;
;;
;;
;; *** Miles Egan: Bytecode
;;
;; I agree that the performance limitations of bytecode are a big drawback,
;; although I don't think bytecode-compiled languages need necessarily be as slow
;; as Python or Java. Ocaml, for example, compiles to bytecode or native code and
;; Ocaml bytecode is often quite efficient. The big advantage of bytecode systems,
;; of course, is that you can transparently mix code written in different
;; languages. This could save you the trouble of writing all those boring but
;; essential support libraries - HTML and XML parsers, database access libraries,
;; image processing tools, network protocol libraries etc. I think that it's
;; really all the high-quality CPAN modules out there that keep Perl going at this
;; point.
;;
;; I'm not any kind of expert on .NET. As I understand it, it is comprised of a
;; common bytecode runtime environment (the CLR), the C# programming language,
;; support libraries for system, network, and web services, and identification and
;; authentication protocols. Microsoft intends it to be the infrastructure for
;; their next-generation web services and the whole environment has been designed
;; with that in mind. Several prominent free software groups, most notably the
;; Ximian folks, have announced plans to build open-source implementations of .NET.
;; You can read about Ximian's plans here: http://www.go-mono.com/. I mention this
;; to you because it sounds to me like they're trying to solve some of the same
;; problems. They plan to implement their own runtime and C# compiler, but I think
;; a better language that could transparently access all the library code the
;; enviroment provides would be very appealing to a lot of open-source web hackers
;; and a lot easier to implement than a completely from-scratch language and web
;; development environment. There are drawbacks too, of course, but I think there
;; are some intriguing possibilites.
;;
;;
;;
;; *** Scott Draves: Zope
;;
;; zope is the closest thing to a lisp machine that i've
;; ever seen, but it runs as a web server, and instead of
;; lisp you have python, which is lisp without parens or
;; macros. there is now a layer on top of zope that
;; adds an asp toolkit oriented towards
;; corporate communications and publishing. the company
;; does consulting using the tools they support as
;; open source.
;;
;;
;;
;; *** Matthew O'Connor: type-narrowing
;;
;; I have a BIRD and a PLANE that each inherit from FLYING_THING.
;; Now some part of my code knows about FLYING_THINGs and in
;; there I have a list of them. I pass this list of FLYING_THINGs to
;; another part of my code that knows about PLANEs. In this section
;; of code I have to be able to take a FLYING_THING and cast
;; (type narrow) it to PLANE if it is indeed a PLANE.
;;
;; This is what OCaml doesn't seem to allow me to do when all of the
;; other OO languages I know allow this.
;;
;;
;; *** Simon Britnell: running remote programs from command line
;;
;; The idea is primarily that it would be easy to publish (small)
;; applications by placing a directory tree on an http server.
;;
;; Presumably there will be some facility to load files, libraries, etc in
;; arc. I think that when a program is run from a url, the directory base
;; in the URL should effectively become the cwd for that session.
;;
;; So that when loaded from http://foo.com/bar.arc:
;;
;; load "baz.arc" ; reads and executes http://foo.com/baz.arc
;;
;; and (excuse my poor lisp/scheme vocabulary here, I actually use scheme
;; very little):
;;
;; open-input-port "blargh.txt" ; opens http://foo.com/blargh.txt for input
;;
;; It would also be nice to be able to specify files to be loaded over http
;; in the arc source:
;;
;; load "http://libvendor.com/graphics/charts.arc"
;;
;; In this example files referred to at the top level of charts.arc will
;; also be loaded from http://libvendor.com/graphics. Functions defined in
;; charts.arc should not necessarily load from
;; http://libvendor.com/graphics, but rather from the cwd at the point they
;; were executed from.
;;
;; In short: load should set the cwd within the scope of the file it's
;; executing to the directory that file was loaded from. It would be nice
;; to be able to get the directory the actual source was loaded from inside
;; a function too, I just don't think it should be the cwd at that point.
;;
;; I think at this point a security modified version of arc becomes
;; important so that you can run untrusted code with confidence. OTOH,
;; perhaps such confidence is better acquired via chroot or some such. I
;; was also thinking about caching frequently used http fetched files
;; locally, but that's what a caching proxy is for.
;;
;; The comment about having a low level (ie. framebuffer) graphics library
;; for easy integration into a web browser was because:
;;
;; a) A low level graphics interface is important anyway for various
;; applications.
;; b) If you can already load files over http easily and your display
;; interface is a framebuffer, integration into a browser is relatively low
;; hanging fruit (replace the url fetching primitive and the framebuffer
;; primitive and you're done) and may appeal to those who (like me) distain
;; java applets as too big and clunky.
;;
;; > If so there would have to be something on the client too. What?
;;
;;
;; I was thinking of having some kind of library macro that would allow you
;; to write the code to be executed on the server in the same source as the
;; code to be executed on the client. The code would be initiated on the
;; server and a client macro would surround the bits to transmit to the
;; client. I need to think more about this area however as it would be
;; nice for the client to be able to return values. The original thought
;; was that the code:
;;
;; (some-server-stuff foo)
;; (more-server-stuff bar)
;; (client (some-fn param (server (baz param)) blah))
;; (continue-with-server-stuff)
;;
;; Would execute the stuff enclosed in (client ) on the client simply by
;; emitting it the text of an http response and that the (server ) stuff
;; would be evaluated into a value by the server before being sent to the
;; client to play with. I don't think this is quite adequate however as
;; (client ) doesn't return a value and http would be an obnoxious protocol
;; to make it work over. Actually, an http post containing a session id
;; for state management and some arc to execute would almost do the job for
;; client returns. You'd definitely want some kind of security
;; restrictions on what client returned code could do.
;;
;; ;; Server code for input from a client side form
;; (update-person (client (input-form "my.form)))
;;
;; Likewise, it would be nice for client code to be able to send ad-hoc
;; requests to the server:
;;
;; (server (get-tax-code (client zip-code)))
;;
;; I need to think about this some more. I've almost got it figured out.
;;
;;
;;
;;
;; *** Peter Armstrong: J
;;
;; There's a quick way for Lispers to get the feel of the J
;; language. John Howland has built a course around a set
;; of programs parallel-coded in J and Scheme! Try --
;;
;; http://www.cs.trinity.edu/About/The_Courses/cs301/
;;
;; and scroll to the bottom for source listings.
;;
;; I should mention also Howland's language Aprol, an attempt
;; to integrate the functionalities of J & Scheme. While the
;; project itself may be inactive, you might be interested in
;; his perspective on such attempts (or even on the logistics
;; of simply calling J from Arc -- which I would find cool!).
;;
;;
;;
;; *** Henrik Ekelund: strings with linebreaks
;;
;; Here is a simple but very good idea taken from Python.
;; In python you can express string literals in more than one way.
;; Short strings can be enclosed by either single quotes OR double quotes.
;; Strings can span more than one row if they are enclosed by three quotes
;; (single or double).
;; It gives very readable code:
;;
;; sqlstring=""" SELECT * FROM TABLE
;; WHERE field='VALUE' AND
;; otherfield='Something' """
;; xmlString = ""
;; cplusplusString = '#DEFINE SOMECONSTANT "Enclosed in double quotes" '
;;
;;
;;
;; *** Sudhir Shenoy: ideas from Perl
;;
;; 1) Please don't use parentheses for s-expressions ('[' and ']' or
;; even '{' and '}' would be preferable. The biggest complaint I have
;; about parentheses is that it makes infix mathematics (which you are
;; planning to introduce in Arc) really hard to read. e.g. (def interest
;; (x y) (expt (-r * (t2 - t1) / (days-in-year)))) reads really badly
;; when compared to [def interest (x y) [expt (-r * (t2 - t1) /
;; [days-in-year])]]. The overloading of meanings of parentheses
;; (grouping + s-expression) which isn't a problem in Lisp may cause a
;; loss of readability in Arc.
;;
;; 2) An idea you may want to look at (from Perl) is how the AUTOLOAD
;; function works. When a function is not found in a module, the
;; AUTOLOAD function is called with the name of the function that was
;; attempted to be executed. You can write code that will (depending on
;; the context) return the name of the correct function.
;; We use this routinely to provide accessors (set/get methods) on Perl
;; class (hash) objects. Another useful application is when you have a
;; container class/struct that holds specialised objects and you don't
;; want to duplicate the interface of the contained objects in the
;; container. Writing a suitable AUTOLOAD function would simply redirect
;; a call to the non-existent method in the container to a real function
;; in the appropriate child object ...
;;
;; 3) Again, from Perl, interpolation of objects inside strings is
;; incredibly useful. Perl makes a distinction between single quoted
;; strings (no interpolation) and double quoted strings (which have
;; interpolation). Although the parser and compiler have to look into
;; strings to see whether interpolation is to be performed, the end
;; result is code that is easy to read and understand.
;;
;;
;;
;; *** Ben Yogman: calling
;;
;; Calling pattern:
;;
;; - There should be requirable keyword arguments.
;;
;; Keywords just specify roles, right? So then not having keyword arguments
;; implicitly assumes that roles are naturally evident by function name and
;; argument position. This goes awry in practice even with just two arguments,
;; and the more arguments you have the worse the combinatorics. Requiring
;; arguments in a certain order is generally an icky thing people do to make
;; function calls cheaper, but the info to swizzle argument lists and the lists
;; themselves will in practice be in place at compile time, as generally you
;; funcall with one or two argument functions that don't need keyword help to
;; disambiguate. By specifying roles, the function calls become not only
;; easier to write, but also better documenting once written.
;;
;; - Optional boolean keyword arguments should go directly into function calls
;; and result in a binding of true in the function body.
;;
;; Again, this makes the calls a quicker and more natural read... just say
;; :verbose, :pretty, :coerce, whatever or don't say it. Many other examples,
;; the only issue is what special syntax for this in the function definition.
;;
;; - The simple OO system's defined methods ought to have a (obj.method
;; ), rather than having the object as the first argument.
;;
;; Like with the previous point, this is to enhance readability... putting the
;; subject first in the expression followed by the verb mirrors a large class
;; of human languages.
;;
;;
;; Function meaning:
;;
;; - There should be operator overloading
;;
;; It's damn useful. I'm not saying string concatenation should be +
;; necessarily (though maybe... having a small minimal working vocabulary
;; really helps the ramping time), but let's say I'm doing something
;; commutative... adding two vectors, or matricies, or polynomials.... you get
;; the idea.
;;
;; - There should be MI, and it should look a lot like trying to use possibly
;; conflicting packages together
;;
;; You have the same problems and you have to solve it once, so why not use it
;; twice? I myself have not used MI much, but I have a little, and it really
;; is the right tool sometimes.
;;
;;
;; Library stuff:
;;
;; - There should be a reader macro predefined for converting infix, reverse
;; polish, whatever... math, logical, and assignment ops to prefix complete
;; with a transparent operator precedence table.
;;
;; Why scare away people when you don't have to? Why make people retranslate
;; formulas? Also, maybe people are used to HP calculators... dunno.
;;
;; - Supply even the really primitve primitives, like bit shifting
;;
;; Even if you don't have an implementation now that takes direct advantage,
;; you could at least infer a more specific type than with /2 /4 /4*N, and you
;; leave the door open for blazing speeds.
;;
;; - Go through CLR and design patterns and have something ready-made to
;; describe what people know from canon
;;
;; Read, find corresponding algorithm and or design pattern... fill in gaps.
;; Macros can kick some serious but here, especially with the design patterns.
;; I'd be very happy to contribute.
;;
;;
;; Random:
;;
;; - There ought to be a reasonable attempt to deduce types, and part of the
;; information that comes back from the REP should be best guess types.
;;
;; That info is directly usefull, though at some point, possibly early, it
;; could go a little stale through layers of indirection. Though in principle
;; algorithm first, continuing to declare types selectively could continue to
;; help, and it certainly won't hurt speed. Also, though the profiler is the
;; ultimate arbiter, you often know at least some of the hot spots in your code
;; before coding them, so you can spot possible bottlenecks.
;;
;;
;;
;; *** Ravi Mohan: refactoring, vm
;;
;; 1)built in refactoring ,introspection,programming IDE
;; suport.
;;
;; I don't know how refactoring would work in functional
;; languages but the refactoring browser works great in
;; samll talk. I guess what i am trying to say is atht
;; the language should be highly introspective (which
;; LISP is ) AND the language release should come with
;; few tools (like the REF browser) . These don't need to
;; be visual candy, the interface can be simple but i
;; suggest that the tools would improve from version to
;; version an dhave a positive feedback effect on the
;; development of libraries etc as they improve.This is
;; one of the great features of smalltalk ,one has a lot
;; of browsers AND one can define ones own. of course the
;; problem with smalltalk is that it is too toghtly bound
;; to its ide. with ARC this should be an optional add on
;; so that one could use arc without the rB, IDE etc so
;; one could for example use emacs .
;; I would once again emphaise the need for the
;; refactorin browserm bcause this is one tool that would
;; "build" in the language idioms and best practices and
;; with the RB itself being extensible...
;;
;;
;; 2)A "standard" VM with excellent documentation.
;; Ideally teh VM should be written i ARC with , perhaps
;; the lowest layer in C for performance. This idea comes
;; from Squeak as well, where the "one language from top
;; to bottom" approach makes it easy to improve the VM
;; etc without switcjing to C.also there needs to be a
;; way of adding new C primitives to the VM (again with
;; mnested name scopes - see my 1 line suggesy\tion in
;; my last letter so one could have a scope like
;; vm.primitives.posix or vm.primitives.networking
;;
;; 3)XML throughout for documentation dataflows etc( i
;; guess this could be oprional ) but this is just a
;; suggestion
;;
;; 4)start a mailing group (perhaps on yahoo) to collect
;; these suggestions ? this would enable folks to respond
;; to other people's suggestions and quickl build a
;; community of intereseted folks.
;;
;;
;;
;; *** Steven H. Rogers: Overloading +
;;
;; I'm glad that you decided not to use + to catenate sequences. A better
;; use of overloading + would be to apply + individual elements a la APL,
;; e.g. (+ (2 3) (4 5)) evaluates to (6 8). If you're implementing strings
;; as lists of characters, this could make for efficient string
;; manipulation that goes beyond regular expressions.