Vocabulary/udot

From J Wiki
Jump to navigation Jump to search

<<   Back to: Vocabulary

u. u executed in caller's context
v. v executed in caller's context

Rank Infinity -- operates on x and y as a whole -- WHY IS THIS IMPORTANT?



These primitive names are implicit locatives. They differ from u/v only when they are executed. The value of the name u/v is looked up and then executed using the namespaces, both private and public, of the caller of the current explicit entity. Namespaces are restored after execution of u./v. completes.

Unlike an ordinary locative:

  • u./v. looks for the value of the name u/v only in the local namespace of the executing entity. The value must be a verb.
  • the name is executed in the implied locale of the caller.
  • the name is executed using the private namespace of the caller rather than the private namespace of the executing entity. This is the only time when J allows a private name to be accessed from a different explicit entity.

The usual use of u./v. is to give a called modifier a way to evaluate its u//v in the context of the calling function.

Information.png In what follows, only u. will be described, and only in the context of adverbs. This simplifies the treatment.

But what is true for u. is also true for v. – in any modifier (adverb or conjunction).


Common uses

1. Allow a user-written adverb to accept for an operand a private verb within the body of its caller – e.g. myplus=.+ below

Au=: adverb : 'u/ y'
Audot=: adverb : 'u./ y'
   
usesAu=: {{
myplus=. +
echo myplus Au y
}}

   usesAu 1 2 3
|value error: usesAu
|       u/y

usesAudot=: {{
myplus=. +
echo myplus Audot y
}}

   usesAudot 1 2 3
6

Adverbs Audot and Au differ only in the use of u. in place of u . Likewise the verb usesAudot differs from usesAu only by calling Audot instead of Au.

Entering the body of adverb Au creates a namespace based on the current locale. This does not include myplus – a private verb inside the body of the verb usesAu. This causes a value error for u at the point it attempts to become (myplus).

In contrast, thanks to (u.) the adverb Audot, after finding the value of u in its own namespace, switches to the namespace that was current just before its body was entered, and executes the value in that namespace. That value, myplus, is defined in the new namespace and is successfully executed there.


2. Within the body of an explicit verb, fetch the name of the locale it was called from:

caller_z_=: {{
echo '+++ caller: entered'
utility 0
}}

utility_z_=: {{
u=. coname
echo 'utility' ; y ; 'called from locale' ; u.''
}}
   
caller_base_''
+++ caller: entered
┌───────┬─┬──────────────────┬────┐
│utility│0│called from locale│base│
└───────┴─┴──────────────────┴────┘

caller_j_''  NB. any locale would serve here
+++ caller: entered
┌───────┬─┬──────────────────┬─┐
│utility│0│called from locale│j│
└───────┴─┴──────────────────┴─┘

This trick shows that u. is not restricted to adverbs (and conjunctions) but is useful within the body of an explicit verb too.

OBSERVATION: Inside a verb definition, as opposed to an adverb definition, u. has no special meaning as the Operand (verbs don't have "operands", they only have arguments). Nor does u – it is simply a private verb. Nevertheless the very fact of its name being u causes (u.) to get replaced by the value (coname) you've assigned to it. You must of course assign the value to u . Not to u. – which is read-only and can't be assigned-to.


3. Within the body of an explicit verb, fetch the name of the verb it was called from:

caller=: {{
echo '+++ Entered: ', me=. 'caller'
utility 0
}}
   
utility=: {{
u=. ".
echo 'utility' ; y ; 'called by verb named' ; u.'me'
}}

   caller''
+++ Entered: caller
┌───────┬─┬────────────────────┬──────┐
│utility│0│called by verb named│caller│
└───────┴─┴────────────────────┴──────┘

NOTE: Unlike #2 above, this trick needs caller to expose something for utility to seek and find. But it is only an innocuous local assignment to a private name, e.g. me. If you try to emulate this technique without the use of u. or v. you will need to assign the verb's name to a global cache (e.g. me=:'caller') – a nuisance to maintain in a large amount of code, besides being prone to conflict between nested callers.


More Information

  1. Remember that u. is a primitive verb having infinite rank.
  2. The operand must already be defined as a verb in the local namespace.
    The local namespace must exist, i.e. don't use u. in a statement entered in the session window (in JQt: the Term Window).
  3. You can use u. in compounds, gerunds, etc.
  4. You can't return a bare (u.). If the returned value (noun or verb) of a modifier is or contains u. it gets replaced by its operand.
    J needs to do this because the returned value is destined for the caller's environment, where a bare u. stands for something else entirely, if anything.
  5. However you can use u. as the operand of another modifier, either bare or in compounds. Executing u. in the called modifier will execute the corresponding operand in its proper environment.
  6. u. must not be used as the operand of a modifier which internally refers to its operand as u or v (in very old J code this may even be x or y). Such a modifier will execute its operand in the wrong environment.
  7. If you use u. in the definition of a verb and then fix the verb using Fix (f.) then u. gets replaced by the current operand and the intended environment is lost.

Details

  1. The environment in the caller that is seen by u. is the environment in force when the caller started executing the called modifier.