Intent

Jason Marshall jmarsh@serv.net
Sat, 01 Apr 2000 09:15:01 PST


>
>From: Jason Marshall [mailto:jmarsh@serv.net]
>
>> Recently, btanksley@hifn.com wrote:
>>Talk of 
>>whiz-bang ways of implementing yet-another-language-with-some-
>>induction-logic is, while interesting, old hat, and does nothing for
>>readability before I've had my morning coffee, which is exactly when 
>>I'm going to botch the code.
>
>Grin.  I certainly understand that.

Here's where things get trickier.  There's a severe shortage of 
programmers
in the good-great category.  We're short on architects (me), and we're 
way
short on artists (also probably me), and so far, software engineering 
has been
an artform, no matter what people try to tell you.  It's really no 
different than
architectural engineering.  You want something to stand up, sure, but 
you
want it to be functionally elegant, and to not fight you all the time. 
I can't
honestly say I'd like that state of affairs to change, but then, the 
'system'
works well for me already. 

Anyway, that wasn't where I was heading with that.  Where was I?  Ah, 
yes.
So since it's hard to find good help, this means I am always going to 
have
at least one coworker who is, essentially, me without my morning 
coffee,
but all day long.  Even barring this, there's always going to be The 
New
Guy, fumbling around as s/he figures out how our codebase functions (or
doesn't, as the case may be).  I would love to be able to stack the 
deck
in favor of the adequate programmer being capable of a significant
fraction of the tasks that a good/great programmer can accomplish.

I want an executive summary of my code.  I further want to be able to
indicate that certain salient features of a module of code are 
non-negotiable.  They are what makes the module functional.  I should
be able to watch that no one comes along and breaks this behavior,
in the name of new functionality, on accident.  DBC and inheritance 
try to accomplish this, but I don't think they cover enough aspects of
the code.

This essentially means that I want a delinter as standard equipment for
developers.  I want to be warned when a feature of my code is lost or
gained.  This should help track down unintended side effects, which 
means fewer bugs.  I have more interesting things to do with  my time,
frankly.
 
>>No one talks of formalized metadata, which is what I am after, and 
what
>>I thought/think Fare is after.  Why?
>
>Because you don't talk about it?  I mean, if it's interesting, talk 
about
>it!  Don't dis my language because I don't talk about what you're 
interested
>in.

Fair enough.

>Okay, the topic is a lot clearer to me.  You want metadata, and you 
want it
>embedded in the language.  IMO, it would be best as an optional thing, 
but I
>don't mind it being required.  You don't actually object to 
concatenative
>languages; you simply want a language with metadata provided.  (You 
should
>have _said_ that, instead of just stating that concatenative languages 
were
>inferior.)

I want explicit metadata as a standard, yes.  If it's not part of the 
design
process, and doesn't improve static checking of the code, then I don't 
know
how Useful it is.  While it's true that a lot of metadata can be 
assigned at the
function/method level, I am still not entirely grasping how you prevent 
loss of information in the translation from brain-to-silicon within the 
body
and signature of the method in a terse form that relies on deductive 
logic.

>Okay, try this on for size: a concatenative language with two types of
>annotation.  The first, in the form ( x -- y ), appears at the 
beginning of
>the word definition and is a type description (x and y may be any 
number of
>type names, seperated by spaces).  The last item in x is the type of 
the top
>of the stack (as with traditional Forth stack comments).  Types are 
handled
>entirely statically, and are fully polymorphic (including return 
values).

>The second annotation, in the form ( x ), appears anytime within the
>definition of a word, and is a stack naming (x may be any number of 
one-word
>names).  Names for stack elements may be traced at compile time, and 
must be
>consistent within a given definition.
>
>example:
> 3 2 ( adder addend ) swap ( addend adder ) + ( sum )
>or
> ( number[myType] number[myType] -- number[myType] ) 
>    ( adder addend ) swap ( addend adder ) + ( sum )
>or
> 3 2 ( adder addend ) swap ( adder ) + ( sum )
>
>The last one of these demonstrates that the stack names don't have to 
name
>everything on the stack.

I'm mostly worried about names between code modules, where most of the
trouble will crop up.  

But if you name the variables, the system can labor to sort out which 
variable
order makes most sense, based on data alignment issues, frequency of
argument use, difficulty of reordering at the caller, etc.  Your 
function 
implementation from four months ago will likely no longer maintain your
optimal ordering as you determined when you first wrote it, and woe be 
unto s/he who changes the order of his arguments after everyone else
is already using his/her code.

>>> Of the two of us, who's more likely to reveal the most intent?
>
>>By sheer volume of citations of intent?  Your users. You wrote the 
code
>>once, and now everyone else is having to live with your mistakes (and
>>you are human, so don't imagine you haven't made any, because you 
have).
>
>You missed my point.  Take two people, you and me, writing code in our
>seperate languages: yours with named parameters and mine being
>concatenative.  Which OF THOSE TWO PEOPLE will reveal more intent by 
means
>of their language's mechanisms which are designed for that purpose?
>
> - The concatenative language is designed for quick, easy factoring 
and
>refactoring, allowing the author to create many functions which work
>together to solve his problem, and leave many component functions 
which may
>be reused.
> - The parameterized language is designed to allow the programmer to 
name
>his parameters, and communicate those names to later reusers.
>
>Both languages have ways of communicating internal intent to the 
external
>world, as well as structuring to preserve internal intent.  Do you 
really
>think that one of these MUST be more revealing than the other?


>>I am familliar with the classes of mistakes programmers in team an 
API
>>settings make, in real development environments.  
>>I understand that Kyle has grasped this, and that you see it as a
>>non-issue.
>
>No, I don't see it as a non-issue -- I simply see many other issues to 
deal
>with, which add up to readability.
>
>Note that Forth traditionally has no type checking at all (although my
>suggestion for type checking, above, is based on a Forth type 
checker), and
>even large projects in Forth don't run into that particular problem 
very
>much -- almost certainly because it's so painful to use large numbers 
of
>parameters in Forth.

I keep bumping into situations where static type checking seriously 
erodes
the advantages gained by reflective code.  Sometimes pushing error 
discovery off until runtime comes back to bite you in the butt.

>>Not in the least.  People want flexibility in a language in case
>>the environment isn't subtle enough for their tastes.  Then they turn
>>around and complain because everyone comes up with a 'clever' synonym
>>for the code they would have written, sometimes correctly, sometimes
>>totally wrong, but either way, totally greek to their peers.  
Formalism
>>takes the edge off such concerns over abuse of power.  Here is your
>>rope sir, but you have to justify any requests to tie it into a knot.
>
>The odd thing is that I think I understand what you're saying (both 
times
>you've said it), and I'm just about certain I agree entirely with it, 
but I
>_still_ don't see what on earth it has to do with our discussion.  
What does
>this have to do with named parameters versus implicit parameter 
passing?

Because formal logical naming of parameters is a type of formalism.  

>>> -- except that you have a huge translation layer, and I have a tiny
>>>    one.
>
>>I have a segmented translation layer, which is an important 
>>distinction.
>
>I have three low-level segments:

> - the quotation system (which defines a 'function structure' and 
provides
>ways of accessing its fields and compiling natively the function it
>indicates; the function structures contain properties such as 
profiling
>data, frequency of calls, and so on; this layer is also written in 
processor
>dependant code).

The segments to which I refer fall within the spirit of your quotation
segment.

>>You have a tiny translation layer, or you're falling victim to the
>>incomplete implementation fallacy?
>
>Well, there are two systems like this that I know of which have been 
in
>commercial use for five to ten years now.  Add a third, if you count 
Elate
>(which uses a similar design but with a slightly different emphasis on 
the
>underpinnings).
>
>>How big is your standard library going to be?
>
>If it includes everything TUNES wants, infinitely large.  However, I 
expect
>it to fit on a floppy.

Okay, so in order to compete on the merit of size alone, my interpreter 
has to provide enough extra value to reduce the verbosity of the core
libraries.  I am hopeful that such will be the case.  That was the 
message
I was trying to get across. 

>>Concerns over how big an 'unabridged' edition of the machine would be
>>have some merit, but not as much as you're attributing to the issue.
>
>Okay, here's the concern I'm expressing: contrary to your statement, I
>believe that my optimiser, with or without metainformation, will 
produce
>compact, efficient code.  I base this opinion on systems similar to 
mine,
>such as Quartus Forth and 4THCOMP.

How do these systems benchmark compared to C or C++ equivalent
code?  I've been curious about how these other styles compare to
the rest of the industry.  

>>There is no requirement that a compiler issue, or the 
>>interpreter honor,
>>any optional data.  If the optional data represents 80% of the
>>dictionary,
>>and 90% of the implementation complexity, who really cares?  All I've
>>done
>>is provide a formal vessel into which optional tools can place their
>>data, in an attempt to avoid ad hoc formats.  What does that hurt?
>>Nothing, according to the industry examples I can find.
>
>Our discussion used to be about a language which _required_ parameter 
names
>to be included in every call.  I don't know what you're discussing 
now, but
>it's definitely not the same thing.  Could you provide an URL, or give 
a
>description of what you're talking about?

I'm discussing things you snipped from my previous letter.  Your 
comment on
size issues I assumed was directed at my general desire to have a 
generic
markup system for the code, of which parameter names were but one
markup.  Apparently I misinterpreted where you were going with that.

>>Different environments will contain a different subset of the content
>>handlers for the language.  My deployment environments won't care 
about
>>debug data.  My dev environment will.  My palm pilot doesn't care 
about
>>MPP or high precision math or vector math, or advanced speed-for-
space
>>tradeoffs.  My workstation doesn't care about space-for-speed 
>>tradeoffs,
>>but when I'm downloading a new multiplayer game off the net, I'd much
>>appreciate if it was usable the first time I ran it.  No VM I know of
>>is giving me that.
>
>Check out Elate, formerly known as Tao OS, at
>http://www.tao.co.uk/2/tao/index.html.  Very cool.  Very similar to 
what Sam
>and I are building, and does exactly what you say.

And commercial, yes?  If I've learned anything, it's that you always 
give the razor
away for free, and then you talk about selling the blades.  Every 
language
someone has forced developers to buy has been marginalized.  You want 
to make
money off a language?  Fine.  You wrote the thing, don't you think that 
qualifies
you to make a killing on consulting contracts?  Books?  Just please 
stop this silly
nonsense of trying to sell the basic runtime.

Regards,
Jason Marshall