

First Priority: Core Language - rms
http://paulgraham.com/core.html

======
andreyf
_That's part of why I focus on code size. Length is an external constraint. If
you start looking at code thinking "what is the lower bound on how long this
has to be?" you're one step from discovering the new operator that will make
it that short._

Paul: Give us a peek into your head... how do you go about discovering new
operators? Do you go to set theory or algebra books for inspiration, or look
over lots and lots of code with an open mind?

Also, how do you decide if a new operator that ought to be something "easily
added" or a part of the language? remove-if-not seems to be something in the
former category.

~~~
pg
That is a good question. I plan to write about that one day. I'm not entirely
sure. I think the process is mainly negative: I look at code that feels bad,
in the sense of being unneccessarily long. If you remove the unnecessary bits,
what's left is a call to the new operator.

One specific heuristic I have is that I love things that make it possible to
put functionality into actual functions that can then be passed as arguments,
rather than having it stuck in the middle of a loop. Programs are easier to
rearrange that way. So : notation for composition and [..._...] for closures
are double wins. They're not only shorter, but also encourage the use of
functional arguments.

Maybe triple wins, actually, because they both get rid of variables, which is
an especially good way to make programs shorter.

You have to iterate, because sometimes a new operator will make it possible to
define more new operators that compress code further. Occasionally a big piece
of code just collapses, like cotton candy in your mouth.

I put stuff in the language if I use it a lot in applications. A lot of the
operators in arc.arc are on probation, because they seem like they might be
useful, but I haven't actually used them much so far.

------
bootload
_"... So I want to ask a favor from Arc users: I want to ask for tolerance
when I break and change things in what may seem to be arbitrary, small ways.
This will make Arc a pain in the ass to write programs on top of, I know, but
the end result should be something worth having. ..."_

This is the bit that will cause a lot of flack. Is there any way to mitigate
code breakage? Is it worth it? Maybe users should confine their coding to
sketches in one problem domain re-solving it each time the language evolves.
Concentrating on how Arc can be improved instead of just the application.

The best bit I got from this post was re-reading "Design and Research". [0] So
the research being done by users, design by pg? Changing the mindset from app
builders to language researchers is difficult but not impossible.

[0] <http://paulgraham.com/desres.html>

~~~
queensnake
> This is the bit that will cause a lot of flack. Is there any way to mitigate
> code breakage?

Don't distract geese that are laying golden eggs - just stand back and keep
very quiet (IMO). I just hope having to deal with this attention and criticism
doesn't hurt pg's motivation or the freedom of his frame of mind.

------
bayareaguy
Why keep the existing primitives? Things like car and cdr were implementation
accidents.

~~~
dfranke
From the FAQ:

 _Why did you keep car and cdr?

Because we couldn't think of any better alternatives. It would have been
misleading to use first and rest or head and tail, because conses are
fundamentally pairs; lists are one thing you can build with them, but not the
only thing.

There's no conventional name in English for the first and second halves of a
pair. If you have to make up names, car and cdr are pretty good choices,
because they're short and the same length and naturally composable (e.g.
cadr)._

~~~
corentin
There's no conventional name in English for the WHAT and WHAT of a pair? :)

~~~
andrewl
Well, you need terms that apply to the first and second halves of a pair as
well as the first element in a list and all the rest of the list. First and
second work for lists of two items, but they don't feel right to me for longer
lists.

Also, they aren't the same length, and that would bother me. I'd prefer left
and rite. Or alpha and omega. Or mom and pop. Then you can compose them into
mop. Or maybe I'd better leave it to Paul, as I obviously can't be trusted
with this kind of thing.

~~~
bayareaguy
I guess I wasn't really thinking about why choose those names. If it was just
that you could have whatever you like - I like (hd x) and (tl x) but that's
me. Or even (0 x) and (1: x) could work. A rose is a rose and all that.

What I was really thinking about were things like why have pairs as a
primitive and why enshrine the idea of lists as pairs linked up in a certain
way?

From ac.scm, it looks like the current set of primitives are:

    
    
      (define (ar-type x)
        (cond 
            ((ar-tagged? x)     (vector-ref x 1))
            ((pair? x)          'cons)
            ((symbol? x)        'sym)
            ((null? x)          'sym)
            ((procedure? x)     'fn)
            ((char? x)          'char)
            ((string? x)        'string)
            ((integer? x)       'int)
            ((number? x)        'num)     ; unsure about this                                                                                
            ((hash-table? x)    'table)
            ((output-port? x)   'output)
            ((input-port? x)    'input)
            ((tcp-listener? x)  'socket)
            ((exn? x)           'exception)
            (#t                 (err "Type: unknown type" x))))
    

So why that set? Why have chars _and_ strings _and_ symbols? Why have integers
_and_ numbers?

------
fab13n
_The cond macro, for example. It had all those gratuitous parentheses [...] I
wouldn't be surprised if someone had already discovered the Arc trick of
collapsing if and cond into one operator_

That's done among others by metalua. In AST view, an if-then-elseif-end
statement is seen as:

    
    
          `If{ cond1, block1,
               cond2, block2,
               ...
               condn, blockn,
               default_block }
    

Qi also did a great job of cleaning up a lispy syntax. Too bad it hasn't got
macros...

------
nickb
>While Arc includes some handy libraries for writing web apps--libraries so
powerful, apparently, that it's cheating to compare Arc to other languages
using a problem that requires saving a string on the server--that is not the
focus right now.

HAHA... great quote, pg!!

As for language features, I think Arc's on the right track. If anything, be
flexible and don't resist the urge to change everything. At this stage, the
main thing is to get core right and not worry about backward compatibility.

~~~
olavk
> libraries so powerful, apparently, that it's cheating to compare Arc to
> other languages using a problem that requires saving a string on the server

It is kind of a straw man though, but he also got a point. Clearly the use of
continuations allows very compact descriptions of multi-page control flow. The
only languages that can match the succinctness of Arc in the Arc-challenge are
other lisps, Ruby and Smalltalk/Seaside, which all of them also uses
continuations. Python which is otherwise known for succinctness but which
doesn't expose continuations, does not allow such compact code.

On the other hand it is a straw man because you would not use continuation for
navigation in real-world production web sites. You would have to store a
continuation for every hit on the site forever, which is clearly not scalable.
Therefore it is obvious that serious web frameworks uses other approaches more
in line with the stateless nature of HTTP, even if it leads to more verbose
code.

I still think the arc-challenge is fun (and I agree that brevity is very
desirable), but I think it would be more "fair" if it was framed with real
world requirements (scalable, pages bookmarkable etc.) rather than random
constraints (the user input must not be exposed in the URL) which only serves
to disqualify some non-continuation-based frameworks.

Continuation-based web frameworks suffers IMHO from the same mistake as
ASP.NET - trying to make web development look like traditional application
code. ASP.NET tries to make it look like event-based desktop GUI app
development, Arc tries to make it look like a long-running interactive app
written in a function style.

What web-frameworks are really trying to, is to create a new kind of DSL which
embraces the spirit and constraints of the web rather than try to hide it. We
are not there yet, and such a holy-grail web app DSL might very well be
written in Arc one day. It would probably be very short then.

~~~
olavk
OK, I just realized that the example in the Arc-challenge might be possible to
implement without the use of closures persisted between requests.

If the page URLs are generated from the expression tree - outer expression is
"/said", page 2 is "/said/anonymous1", page 3 is "/said/anonymous1/anonymous1"
or something like that, the framework could locate and execute the correct
expression for every hit. The framework would have to be smart enough to
detect that the "foo" input to the page 2 is used on page 3, so it is passed
on in the generated link. This approach could actually be fully scalable.

(But damn! It would be disqualified because the input is passed from page 2 to
3 in the URL. I suppose it would be cheating to encrypt it?)

~~~
aston
Hint: many web stacks suppport server-side sessions. Via cookies.

~~~
olavk
Yeah, but you don't want to keep navigation state in the session. Otherwise
you have to keep the session alive indefinitely to support bookmarking. Also,
session based navigation state breaks if you browse the site in two tabs at
the same time. And it breaks the back-button.

~~~
aston
pg's server-side closures are just a variation on the session theme, except
that the data being stored is a procedure.

You've just listed a bunch of flaws evident on this very forum . Any link with
fnid as a parameter is pointing to a server-side session closure that might
expire before you actually click the link.

~~~
olavk
OK, agreed, I took your "hint" to indicate that you believed the problem could
be solved by cookie-based sessions.

------
Hexstream
"My first priority with Arc right now is the core language--those operators
that are neither primitives like car and cdr, nor special-purpose library
functions. I mean operators like CL's mapcar, let, remove-if-not, and so on."

let is a special form (at least in CL) so it's a primitive, no?...

~~~
pg
That's funny. I forgot let is a special form in CL. It doesn't really need to
be, and it isn't in Arc.

    
    
      (mac with (parms . body)
        `((fn ,(map1 car (pair parms))
           ,@body)
          ,@(map1 cadr (pair parms))))
          
      (mac let (var val . body)
        `(with (,var ,val) ,@body))

------
cstejerean
I think if this had been written earlier (and instead of the Arc challenge for
example) more folks would better understand the actual goal of Arc.

