Jump to content

Vocabulary/fdot

From J Wiki

>> <<   Down to: Dyad   Back to: Vocabulary Thru to: Dictionary

u f. m f. Fix Adverb

Rank -- depends on the rank of u -- WHY IS THIS IMPORTANT?



Gives tacit verb u an equivalent value without name dependencies.
The word fix means 'nail down', not 'repair'.
u f. is the value of u with each name replaced by name f. .
So even if names refer to other names, the fixed form contains nothing but J primitives.
(u f.) is equivalent to (u f: 'all').

   sum=: +/
   count=: #
   by=: %

   mean=: sum by count
   mean
sum by count
   mean f.
+/ % #

Common uses

1. To reduce the number of public names used in a verb definition.

Consider the following lines in a script:

   '`sum count by log' =: +/ ` # ` % ` ^.  NB. Same verbs as above, assigned quickly
   mean =: sum by count
   gmean =: mean&.:log                     NB. Geometric mean
   gmean
mean&.:log
   mean
sum by count

Suppose that gmean is the only definition you really need to be public. Unfortunately, the other names must also be public, polluting the common namespace, because gmean refers to them.

You can fix this:

   '`sum count by log' =. +/ ` # ` % ` ^.  NB. Use private assignment for temporary names
   mean =. sum by count
   gmean =: mean&.:log f.                  NB. f. makes temporary names go away.  Assign gmean publicly
   gmean                                   NB. All the names are gone
(+/ % #)&.:^.

Because these lines are in a script, the names assigned privately (using =.) disappear after the script has loaded, leaving only the name gmean publicly assigned.

2. To pass a private verb into a modifier.

   a =: adverb define
u y
)
   vb =: verb define
pv =. *:    NB. private verb
pv a y   NB. pass pv into a, execute (pv a) on y
)
   vb 5
|value error: pv

The problem is that pv is defined in the private namespace of vb and is not visible to a. The solution is to replace the name pv by its value using (f.)

       u y
   vb =: verb define
pv =. *:    NB. private verb
pv f. a y   NB. create the name-free verb value for pv, pass THAT to a
)
   vb 5
25

3. To create special code combinations unrecognised by J because some J code was assigned to a name

   ts =: 6!:2 , 7!:2@]     NB. Verb to find the time and space used by a sentence

   a =: 1000 1000 ?@$ 0    NB. create 1 million random values
   ts 'plus/@enfile a'     NB. the worst of times
0.322007 8.39059e6
   ts 'plus/@enfile f. a'  NB. the best of times
0.00179939 4736

4. To execute a verb in another locale without changing the current locale

This is part of J's standard Object-Oriented Programming (OOP) support

   coclass 'parent'
NB. Create object.  y is the name to give the object
   create =: verb define
objname =: y
)

   coclass 'child'    NB. child class
   coinsert 'parent'
NB. Create object.  y is the name to give the object
create =: verb define
create_parent_ y
)

   coclass 'base'     NB. Back to main session
   NB. Create two objects
   obj1 =: 'object one' conew 'child'
   obj2 =: 'object two' conew 'child'
   NB. Verify obj names are what we set
   objname__obj1      NB. Unexpected result...
object two
   objname__obj2
object two

The error is subtle, in the line

create_parent_ y

Executing a locative changes the implied locale before executing the verb. So create_parent_ was run in the locale: parent for both objects.

The solution is even more subtle. It uses f. to call create_parent_

   coclass 'child'
NB. Create object.  y is the name to give the object
create =: verb define
create_parent_ f. y
)
   coclass 'base'      NB. Back to main session
   obj1 =: 'object one' conew 'child'
   obj2 =: 'object two' conew 'child'
   objname__obj1       NB. Better
object one
   objname__obj2
object two

   create_parent_ f.   NB. 'create_parent_ f.' is not a locative
3 : 'objname=:y'

The key point is that create_parent_ f. is not a locative. The locative has been replaced by the value of the name, and executing that value does not change the implied locale, so objname is created in the instance locale.


More Information

1.  u f. does not replace names inside the body of an explicit definition.

We can redo the mean example using mostly explicit definitions

   sum =: verb define
+/ y
)
   by =: %
   count =: verb define
# y
)
   mean =: sum by count
   gmean =: verb define
mean &.:^. y
)
   gmean f.
3 : 'mean&.:^.y'

The name mean in the body of the explicit definition was not altered.

   mean
sum by count
   mean f.
3 : '+/y' % 3 : '#y'

Fixing mean replaces names by their definitions, but it doesn't go inside the body of an explicit definition.

2. A modifier can be fixed by passing the character array of its name as the m operand to m f.:

   Until=. {{u^:(-.@:v)^:_}}  NB. conjunction; apply u until condition v is true
   adv  =. Until (1&>:)       NB. adverb created by supplying one operand to Until
   adv
Until(1&>:)
   adv f.                     NB. a modifier train; not what we want
adv f.
   'adv' f.                   NB. adv cannot be passed as operand to (f.), but 'adv' can
2 : 'u^:(-.@:v)^:_'(1&>:)
   adv=: 'adv' f.             NB. adv is now fixed

Because it is a modifier, adv cannot itself be passed as an operand to f.; the phrase adv f. creates a modifier train which applies adv to its operand, and then fixes the verb derived by the execution of adv.

If we're exporting adv from the current script, this does not help us, since adv depends on the private name Until, and so will fail with a value error when applied to a verb outside of the current script. But the character array 'adv' can be passed as an operand, yielding the fixed adverb.

3.  u f. scans u for special code combinations after replacing names.


Details

1. If a name is referenced recursively, it will remain after fixing

   a =: b
   b =: a + c
   c =: %
   a f.
a + %

2. The interpreter may find it necessary to use $:: to limit the scope of a recursion ($:):

   r=: $:@<^:*
   r@>: f.
$:@<^:*$::@>:
u y
:
x u y
)

3. When the names x y u v m n are used during execution of the body of an explicit definition, they are replaced by their value (even if their value is not a noun), because their meaning changes depending on which private namespace is in use. This replacement does not fix the name (as in  u f. ) but merely replaces it with its value, which may be another name.


u f: n m f: n Fix (partial) Conjunction

Rank -- depends on the rank of u -- WHY IS THIS IMPORTANT?


(u f: n) is like (u f.), but n is a string specifying what subset of the names in u are to be replaced. Words in n mean:

  • single - only the name of the u argument itself is replaced. If single is not given, the value of each name encountered is also scanned for replacement, recursively.
  • private — private names are replaced.
  • public — public non-locative names are replaced.
  • all — all public names, including locatives, are replaced.

private, public, and all are mutually exclusive; if none is given the default is private. u f. is equivalent to u f: 'all'.