Correct Formulation of ME and MY

The ME function is used with enfix to allow you to avoid repeating the name of a variable:

>> variable: 10

>> variable: me + 1
== 11

>> variable
== 11

So that's the same as if you'd written variable: variable + 1.

There's an analogous operation for non-enfix functions called MY.

>> block: [a b c]

>> block: my next
== [b c]

>> block
== [b c]

So the same if you had written block: next block.

Here Is The "Naive" Macro Implementation of ME

me: enfixed macro [
    'left [set-word! set-tuple!]
    'right [word! tuple! path!]
][
    reduce [left, plain left, right]
]

So the macro is looking for a SET-WORD! or SET-TUPLE! on the left, and then something indicating the action to run on the right. It replaces the whole sequence with what was on the left, then a plain WORD! or TUPLE! version of what was on the left, and then what's on the right.

MY is done similarly, just with reduce [left, right, plain left] to put the repeated term after the call.

This is naive for two reasons:

  • It doesn't check that what the RIGHT parameter looks up to is an action

  • If the SET-TUPLE! in LEFT has a GROUP! in it, then it will be executed twice.

Here is A "Non-Naive" Implementation of ME

macro [
    'left [set-word! set-tuple!]
    'right [word! tuple! path!]
    <local> value
][
    [left value]: resolve left  ; avoid double-evaluation
    :['set left meta value ensure action! get right]
]

The RESOLVE function is used to turn a TUPLE! or PATH! with groups in it into an inert representation:

 >> blk: [a b [c d]]

 >> resolve 'blk.(print "hi", 1 + 2).2
 hi
 == @[blk 3 2]

GET and SET accept these blocks as an alternative to words/tuples to be used to describe what to set or get.

It has to use a BLOCK! representation because not all things can be represented in paths that can be used with picking (note this implies you cannot pick with isotopes, otherwise not all blocks would be resolvable).

So long as RESOLVE is walking the path, you can ask it to give you back the value of what's there.

But the non-naive version triggers a binding bug...

It's also rather slow. In trying to prioritize, it may be better to just document the right answer, as I've done here... :-/

3 Likes