I can try, but first I'm going to reiterate that this is a very complicated solution to a very simple problem that should be solved by initialilzing the variable before calling the block. We are still going back and forth about the fact that you want variables to have types, and they don't.
Lists are a mutable data type. If you use a list as the input to your ADD TO LIST block, then your block can mutate the list (just as the primitive one does), whether or not the list is the value of a variable. You'll be able to say ADD 3 TO LIST (ITEM 5 OF FOO) or ADD 3 TO LIST (LIST 1 2 8) or any list-valued expression. Whereas what you're trying to do is restrict your block so it only works in the special case of a variable whose value is a list.
Okay, now to answer your question.
Ordinarily, , like most programming languages, uses applicative order evaluation. This means that when you call a procedure, the evaluator first evaluates all the input expressions, and then calls the procedure, giving it the input values. So when you say (5 + (3 * 4)), the + block knows only that its input values are 5 and 12. It doesn't know whether you said (5 + 12) or (5 + (24 / 2)) or (5 + FOO) where FOO is a variable whose value right now is 12.
This is mostly what you (generic you) want, and almost always what you should want, so that your block doesn't have to know who's calling it and why. It just does the job it contracts to do.
But there are a few situations in which applicative order evaluation doesn't work. The canonical example is writing a conditional operation, such as reporter-IF. That's now a primitive in , but it didn't used to be. At first glance it seems like it should be easy to write:
and this does work in easy situations:
But it doesn't work in the very important case of the base case test of a recursive procedure:
Why not? Because of applicative order evaluation. If you ask for (factorial 0), it's not going to work if the call to the IF block first evaluates its three input expressions, then calls IF with the three values. Why not? Because the third one involves a request to compute (factorial -1), and that will ask for (factorial -2), and so on forever.
Well, as it turns out, has (and has always had, from BYOB3) a solution to this problem: use functions as the THEN and ELSE inputs to IF. Functions are a way to make an expression but not evaluate it right away. So we change the IF block:
This version will work, but it's a little ugly. The block itself looks like this:
and its use in FACTORIAL looks even worse:
(We need the VALUE function, which just reports its input, because you can't type a number into a reporter-type input slot.)
Okay, you still following? Recap: The easy version of IF doesn't work. We can fix it by using the fact that we have first class procedures to delay the evaluation of the THEN and ELSE expressions. The IF block will then pick one of them to evaluate based on the value of the first input. But the cost of this is making the interface to IF kind of offputting.
It's important that you understand that as far as being able to do the job is concerned, we've already solved the problem. It's just the notation we don't like.
So, we want something that looks like the first version of IF, but works like the second one. Saying that another way, we want a special kind of procedure whose inputs knows not to evaluate. Historically, that "special kind of procedure" is called a special form. (Fine print: Programming language mavens will tell you that a special form isn't a procedure at all. It's a special syntax that may look like a procedure call but is really something else. In muggle languages there are tons of special syntaxes, for IF, WHILE, FOR, all those things. But muggles expect to have a zillion different syntactic forms, so they don't think of them as "special.")
In we allow "specialness" to be determined for each input slot; traditional Lisp has it all or nothing. So, in the case of the IF reporter, the first input doesn't have to be special, because it's definitely going to be evaluated first thing, so we can let the evaluator take care of that before calling IF. But the other two inputs are going to be declared "Any (unevaluated)." This means exactly the same thing as if they'd been declared Reporter type, i.e., the expression is turned into a procedure as if it had a ring around it. But the notation is different; what the user sees is a rectangular Any-type slot. The ring is still there, so to speak, but it's hidden.
That's the story. Still not clear? Ask a more specific question.