[REBOL] Re: Antwort: Re: WYSIWYG programming
From: jeff:rebol at: 27-Oct-2000 9:09
Howdy, Joel:
> I really cannot emphasize enough how much I
> appreciate having someone from RT giving us the benefit of
> your perspective on these issues!
>
> (May I respectfully reserve the right to disagree, however?
> ;-)
Yeah, but when we respond then you guys don't let us off the
hook and you hold us to the fire!! :-) Hah hah -- Just jokin
around, ya-know!
> ON FRUSTRATION
>
> 3) The language does not have sufficient documentation to
> allow the programmer to learn the language -- without
> exhaustive trial-and- error experimentation.
We've lost Carl for weeks on end while he did a rewrite of
our docs for reason 3 above.
> 4) The language has features whose complexity requires that
> the programmer keep up with more "moving parts" and
> exceptions to be able to use them safely.
Few things in REBOL can be generally classed number 4 above
-- or at least fewer things than many (most) other languages
out there. Simple things are simple to do, and you can do
hard things too (but hard things can still be hard!).
> 5) The language has features that are "emergent properties"
> rather than "designed concepts" -- that is, they are
> consequences of the interactions of other features of the
> language which even the language designer(s) may not have
> intended or anticipated.
The above is by design, just like strategy is an emergent
property of chess which is based on simple movement rules of
the pieces. REBOL is full of these things, where you
suddenly realize a new use for an old function.
You suddenly realise that instead of:
either found? val1 [foo: val1][
either found? val2 [foo: val2][
either found? val3 [foo: val3][
foo: default-val
]
]
]
you can just do this:
foo: any [val1 val2 val3 default-val]
All this time you might have thought ANY was just this lazy
conditional evaluator, to be used only after IF or EITHER,
but really it makes for a very useful value selector by
placing values in it in the order of precedence. This
arises from a simple rule in the design of REBOL that all
functions that can return a value do.
Here's another one of those type emergent language
capabilities (a kind of silly one that I'm fond of):
to-tuple loop 3 [append [] random 255]
Above capitalizes on the nature of literal blocks and the
fact that loop returns a value. Or:
if loop 20 [do-something now/time > 12:00:00] [print #afternoon]
These emergent properties constitute the expressiveness of
REBOL. Fluency in REBOL is a matter of finding slicker ways
to express things (I think ANY is much slicker than EITHER
EITHER EITHER (-:).
> 6) The implementation of the language may be faulty --
> compared either to its published specifications or (absent
> such specs) the initial intentions of its designer(s).
By any other name: BUG. Yes, software has bugs. Bugs are
frustrating.
> 7) The language "grew" rather than being "designed".
The language's design grew. Carl has spent 15+ years
designing REBOL, building different prototypes of REBOL. An
amazing amount of attention to detail has come from this.
The basic core of the language reflects this great design
legacy, and is witnessed in the consistency of how datatypes
work, the language's seamless polymorphism, and the general
benevolence of the language (by that I mean that REBOL tries
to help you wherever it can-- it's like there's always a
coat hook placed exactly where you want to hang your coat).
The areas where REBOL has "grown" is in the "features"
layer. Features are sometimes added which don't support the
full gamut of operations that most other datatypes have, or
they have some exception to a rule. Features occasionally
break the consistency that the design of REBOL has sought
(in my opinion very successfully) to achieve otherwise.
> Again, the further we go down this list, the more we have
> to shift our focus to the concepts, notation,
> specifications, implementation, and documentation of the
> language (and away from the programmer) as the causes and
> remedies of the frustration. Note especially on #6 that
> the absence of a published specification means that it is
> not possible, even in principle, to state definitively
> whether a given instance of questioned behavior is an
> implementation bug!
We all want to understand what hurdles people face in
learning and adopting REBOL. We rap about this often in the
office, and your breakdown above is pretty good, though I
would throw out 7, 5 and 4 and just look at the remaining
issues: Bugs and docs. To those two I'd add support. A
user entering into a new language like REBOL wants to know
they can find a thriving community of users that can pass
along guru tips and quickly diagnose and help them through
newbie problems. They want tutorials, and FAQs and how-tos,
and cool examples, etc. REBOL Tech.'s worked hard on
providing a lot of that stuff, and many others have as well,
but this is one big area where any one can contribute in a
meaningful way to the spread and adoption of REBOL.
(As Dan recently mentioned, we're also working on a
contribution system where people can contribute to the
language more directly. Basically this will entail the
generous programmer giving us the copyrights to their
contributed source code so, that if we decide it's appropriate
and of a quality to include, we can place it in the core, or
include it in the distribution. We'll also add a contributors
page to our web site with a description of what someone has
provided. We hope this will be a great way for people to add
to the language for the benefit of all. More details to come
soon!!)
> and the results of converting integer! values to other
> numeric types
>
> >> to-decimal 0 < to-decimal 1 == 1
> >> to-decimal 0 <= to-decimal 1 == 1
Uh, I think you want:
>> (to-decimal 0) < to-decimal 1 == true
>> (to-decimal 0) <= to-decimal 1 == true
Think of the infix < and <= operators as shifting around
prior to evaluation to become prefix operators. The first
case would then actually be interpreted as:
to-decimal (< 0 to-decimal 1)
to-decimal (<= 0 to-decimal 1)
Here is a case of a subtlety about infix operators that may
occasionally bite people (one for the docs). The general
rule I use is "compound expressions on the left side of an
infix operator must be parenthesized". Or, "always put
compound expressions to the right of an infix operator", eg:
0 = to-integer "0" == true ;- correct
to-integer "0" = 0 == 0 ;- not what you want
The second case yields: to-integer (= "0" 0)
> Now, notice that we aren't allowed to compare logic!
> values????
>
> >> to-logic 0 < to-logic 1
> ** Script Error: Expected one of: integer! - not:
> ** logic!. Where: to-logic 0 < to-logic 1
The error above is complaining because that expression is
seen as:
to-logic (< 0 to-logic 1)
But in either case...
> >> false < true
> ** Script Error: Cannot use lesser? on logic! value.
> ** Where: false < true
[...]
> On the other hand:
>
> >> pick foo true == "a" pick foo false == "b" fum: true
> >> == true foo/:fum == "a" fum: false == false foo/:fum
> >> == "b"
>
> So, we can't compare logic! values, apparently due only to
> some type-checking rule in the comparison operators. But
> if we could, the way they inter-convert with integer!
> values would lead us to conclude that FALSE precedes TRUE.
> But that is inconsistent with the fact that the TRUE-th
> position of a block precedes the FALSE-th position of the
> block!
A key point here is that REBOL is context dependent.
Because TRUE means something in the context of PICK, it does
not necessarily imply an ordinal ordering of logic values.
People usually think "TRUE" "FALSE", in that order. EITHER
places the TRUE block first, the ELSE/FALSE block second.
Pick thinks of TRUE/FALSE in that way. Now when someone is
converting a logic value to a number they usually have a
different expectation: TRUE being 1, and FALSE being 0.
That would be my normal expectation, but now we have two
clashing expectations if we consider them together (as you
have done here). Should we change it so that we have:
EITHER condition [FALSE-BLOCK] [TRUE-BLOCK] to accomplish
some consistency with logic datatypes? NO WAY! The best you
can do with things like this is to have the language be
context dependent.
RETURN means something totally different in a layout than it
does in a function body. The great aspiration for the
language once it has booted to the prompt is that things
mean what they mean where ever they mean it in the most
intuitive way (--now say that 3x fast! (:). Whenever we run
into situations where we say "gee, that really dosn't work
the way people would 'normally' expect" we fix them. In the
next releases there are some fixes like that, for instance
to-binary of a tuple and inserts and joins on binary values
have recently been fixed to work as people more generally
expect.
> Except my passing reference to common convention, all of
> the above discussion has to do with completely REBOL-ish
> things: comparing REBOL values, converting between REBOL
> datatypes, and using REBOL values to pick values from a
> block.
>
> This is only a tiny, somewhat arbitrary, example; I hope it
> helps convey that the issue is not simply an inexperienced
> programmer complaining that REBOL is not
> Visual-PerlGOL-2000-Octothorp!
You make many valid points, Joel, but let's boil it down to
the three basic issues: fixing bugs, adding docs, and
(community) support. Switching pain is exacerbated by lack
of those three things. Adoption of REBOL is hindered by
switching pain. REBOL Tech should work on the first two and
try to facilitate the third as much as possible.
The thing I just want to exclude from the equation is the
design of REBOL. REBOL's design is solid and remarkably
consistent, but most importantly it is context dependent.
The odd cases where we do get bitten by apparent
inconsistencies are far less than the ongoing experiences
people have with REBOL where things DO work the way people
expect them to. When something does not work in the way the
average user would expect, let us know (you all are very
good about that!) and we'll throw those in the bug pile and
fix em! :-)
Saludos--
-jeff