I'm very pleased with the choice to make methods use dot as the way to refer to "self".
>> obj: make object! [foo: 10 bar: lambda [<.>] [probe ., .foo + 20]]
>> obj/bar
&[object! [foo 10, bar: ~&[frame! []]~]
== 30
>> obj2: make obj [foo: 1000]
>> obj/bar
&[object! [foo 10, bar: ~&[frame! []]~]
== 1020
This really makes it easier to see where you're reaching outside of a function body to variables defined from outside. Rebmake is one of the first places where I really began to want to know where all these invisible inherited variables were coming from, and the dot helps them stand out.
But You Don't Need A Method To Use The Trick
Assigning dot via a SET-BLOCK! ([.]:) looks a little better than assigning it via SET-WORD! (.:)
>> [.]: {x: 10 y: 20}
>> .x
== 10
>> .y
== 20
You can just do that anywhere. And in fact, I found it was a pretty good mechanism for dealing with what I used to use <with> for.
test-failures: 0
successes: 0
skipped: 0
; <bunch of functions and stuff>
run-test-cluster: func [
return: []
flags [block!]
cluster "Block of GROUP!s to be run together in a common isolated context"
[block!]
<with> test-failures successes skipped
][
if not empty? exclude flags allowed-flags [
skipped: me + 1
<blah blah blah>
I had hoped that <with> would get some teeth someday in enforcing that any outside variables that weren't mentioned would be read-only. But that never materialized, and so it was just commentary.
Better than this is:
[.]: {
test-failures: 0
successes: 0
skipped: 0
}
; <bunch of functions and stuff>
run-test-cluster: func [
return: []
flags [block!]
cluster "Block of GROUP!s to be run together in a common isolated context"
[block!]
][
if not empty? exclude flags allowed-flags [
.skipped: me + 1
<blah blah blah>
This helps a lot.
It's more subtle than leading underscore. And it's different from a naming convention (like leading underscore, for instance) because you can do things like import the . into a scope where you want to use the undecorated names:
assert [.foo = (eval bind . [foo]]
I'll mention that I'm thinking that USE should be an in-stream version of EVAL BIND:
assert [.foo = (use ., foo)]
Then what we call USE today would be WITH, as a synonym for EVAL BIND.
Should We Continue the Pattern With .. and ... etc?
We could imagine that TUPLE!s like ..foo and ...bar would be ways of referencing .. and ...
Today such TUPLE!s with multiple leading blanks aren't legal. But should we allow it?
![]()
I kind of don't like it. I've been fairly happy with the "only blanks in head and tail position of sequences" rule.
Another maybe silly reason is that I really like ... meaning "nothing here yet" and being seen as something that panics if encountered.
But we can think about it.