[Python-ideas] Modern language design survey for "assign and compare" statements

Tim Peters tim.peters at gmail.com
Sun May 20 15:01:19 EDT 2018


[Tim]
>> I was an early REBOL user, and my head still hurts ;-)  It was ...
>> different, for sure.

[Steven D'Aprano <steve at pearwood.info>]
> Yeah, to me it looks more like a prefix version of Forth than Lisp.
> Complete with "anything can be a name":

The example I gave just strung "words" together, but just as
fundamental is the notion of "block":  a series of words and/or blocks
enclosed in square brackets.  That's akin to Lisp's "S expressions",
but Rebol/Red _don't_ "evaluate" blocks by default.  Blocks can hold
data or code, or a mix of both, and the syntax doesn't care.  That's
the real reason "(almost) anything can be a name (word)".

Here I'll build to a simple example where _some_ Pythoneers will
experience envy rather than revulsion ;-)

>> [x y]
== [x y]

The block isn't evaluated.  Depending on how it's _used_, it may be
treated as data (perhaps you want to think of it as being a sequence
of two symbols, or strings).  If you evaluate it, it blows up (because
I don't happen to have any variables with those names defined):

>> do [x y]
*** Script Error: x has no value

Give the names some values, and _then_ it can be evaluated; and
evaluating a block returns the value of the last expression in the
block:

>> x: 12 y: 13
== 13
>> [x y]
== [x y]
>> do [x y]
== 13

If you want a block with all the expressions' values, use `reduce` instead:

>> reduce [x y]
== [12 13]

Code?  Data?  No difference.

Here's the part where some Pythoneers will get jealous:

>> sum: func [x y] [x + y]
== func [x y][x + y]
>> sum 8 2
== 10

`func` is just another function that happens to build an anonymous
function.  It takes two blocks as arguments:  a block containing the
formal argument names, and a block with the code to execute.  Both
blocks are essentially "data" to `func`.  It doesn't look much like
Forth anymore ;-)

Note that the following does exactly the same:

>> arglist: [x y]
== [x y]
>> body: [x + y]
== [x + y]
>> sum2: func arglist body
== func [x y][x + y]
>> sum2 8 2
== 10

In practice, slinging Rebol/Red most feels like working in a
functional language.  One of their real goals, though, is to enable
writing functions that can be called like so:

    schedule "Change furnace filter" [
        starting today
        then every 3 months
    ]

There's an elaborate `parse` function built in that supports many ways
of applying user-supplied rules to parse blocks like the one in that
example.

Of course you can emulate much the same in Python by, e.g., passing
triple-quoted strings instead.  In that specific example.  Rebol/Red
provide a minimum of syntax shared by all such applications, and when
the sub-language gets elaborate enough that _nesting_ blocks makes
good sense, nesting triple-quoted strings sucks ;-)

All languages have some good things going for them.  But I'm not sure
I've ever seen Rebol/Red code that _used_ the value of an assignment
expression; that it has them at all seems much more to follow from
that everything is an expression.  As in most functional languages, if
you want initialized local variables, you're more likely to invoke an
anonymous spelled-inline function instead.  Which is what, e.g.,
Haskell's "let PILE_OF_BINDINGS in EXPRESSION" is syntactic sugar for
doing.


More information about the Python-ideas mailing list