Vocabulary/Locales

From J Wiki
Jump to navigation Jump to search

Back to: Vocabulary

Locales

When you assign a name, e.g. like this:

   myverb =: +
   mynoun =. 5   NB. inside a verb definition body

the name mynoun or myverb always resides in some given namespace.


Summary of the Locale Mechanism

If you already understand locales, here is a refresher. Otherwise skip to the next heading...

  • A locale is a public namespace. A locale is created whenever you create or refer to a name in the space.
  • Every action on a name - an assignment to the name, or a reference querying its value - has a starting locale.
  • At all times there is an implied locale that will be used as the starting locale if not overridden by a locative.
  • A locative is a name that includes within it the namespace to use as the starting locale (instead of the implied locale).
    • name_locale_ means "name with locale as the starting locale".
    • name__instance means "name with the value of instance as the starting locale".
  • Each locale has an associated search path, a list of locales. By convention every search path ends with the locale z. You can change the search path at will.
  • References to public names begin the search in the starting locale. If the name is not found in the starting locale, lookup continues with the locales in its search path until the name is found.
  • Public assignments are always made in the starting locale.
  • When an entity named by a locative is executed (example: names_z_ ''), the implied locale is changed to the locale given in the locative, and changed back after execution.
  • An instance of a class named newclass is created by a line like
    instancename =: (creation_parameters) conew 'newclass'
    which creates a locale for the instance, associates it with the class newclass, executes the create verb in the instance, and returns the locale name of the instance.

Namespaces and locales

There are two kinds of namespace:

J creates one of these when it starts to execute an explicit verb, and destroys it again when the verb stops running. This namespace holds private names defined in the body of the verb, which avoids name clashes with names defined outside the body.
A private namespace is created for explicit modifiers too, when they start executing the body

This kind of namespace is called a locale. J creates one of these when you ask for one, or when it evaluates a locative.

A named locale, also called a class locale, has a name, chosen by its creator, typically you. A numbered locale, also called an instance locale, holds an instance of a class, and is given a system-assigned numeric name when the instance is created. You use either type of locale-name by writing it into an extended kind of name called a locative, as described below.

A locale-name is a list of characters. In a numbered/instance locale, the characters are all numeric, for example '124', and an atomic integer can be used to name the locale.

Locales are chiefly used to avoid name collisions between software packages, or to create an object-oriented class instance.


The base locale and the z-locale

There are two locales which you can rely on always being present:

  • base (aka the base locale) — the default locale that J starts up in
  • z (aka the z-locale) — containing standard library (stdlib) words which are always visible, i.e. they behave as if they are defined in every namespace.

See Vocabulary/ZeeLocale. z-locale also contains the few names that constitute the public interface to packages, such as addons or packages that you might write.

You could in principle do all your work in the base locale without knowing about locales or locatives. But when you come to write a significant application for distribution, or try to understand the workings of distributed applications, e.g. addons, then it's vital to know how locales and locatives work. See below: How to work with locales and locatives.


What makes a locative?

To form a locative, typically you join a locale name, e.g. myloc, to the simple name of your entity, e.g. myverb, like this:

   myverb_myloc_ =: +
   mynoun_myloc_ =. 5

But that's not the only way.

In general, a locative

  • contains at least two underscores (_)
  • consists of a simple name followed by the (designation of the) starting locale
  • the (designation of the) starting locale is one of these:
    • a locale name surrounded by underscores (_). The name can be
      • a valid J name containing no underscores (_)
      • a character string of all digits with no superfluous leading 0 digits
    • a double-underscore (__) followed by a name.

The __name sequence can be repeated.

Q. Can a name contain underscores (_) without J thinking it's a locative?

A. Yes, but ...

  • it must not end in an underscore
  • it must not have two underscores together.

When discussing locatives, "by abuse of terminology" (to paraphrase WikiPedia:Nicolas_Bourbaki) we shall simply say

  • "the entity" when we mean the simple name of some entity (noun, verb, etc.)
  • "the locale" when we mean the name (or other valid designation) of some locale.

A good way to understand locatives

Our explanation of locatives is alas going to be somewhat complicated.

But a good way to understand them is to recall how files are structured in Windows(TM), enabling you to distinguish between files having the same name in different directories (aka "folders).

  • A filename may or may not have a path description attached to it. If it does, it's called "a pathfilename", or sometimes just "a path".
  • The path description may not take you straight to the target file. It may point instead to the start of some (configurable) "search path" stored elsewhere.
  • There is such a thing as the current directory, which in certain limited circumstances lets you (optionally) omit the path description from a given filename.

WikiPedia:Unix and Apple(TM) WikiPedia:Macintosh have comparable schemes, differing mainly in syntax.

J uses a comparable way of locating entities having the same name in different locales. But the syntax is different.

You can make a pretty good prediction of how locatives behave if you mentally substitute

  • "file" for "entity" (noun, verb, etc.)
  • "directory" for "locale"
  • "current directory" for "implied locale"
  • "path/filename" for "locative".

Failing that, read on...


Explicit locative and object locative

There are two ways of joining a locale to a simple name to produce a locative:

the starting locale is the string between the two underscores.

the double-underscore is followed by one or more names of nouns whose values give the starting locale. Each value must be a boxed string.

Exception: A locative of the form:  myverb__ (i.e. with two trailing underscores) is equivalent to  myverb_base_ .

Since the base locale typically serves as a receptacle for test data, this form of locative, e.g. y__ , is a convenient way of exporting test data from within a verb body.

If the original name was not a locative, then it is itself the simple name in question.

What does it mean when two or more locales appear in an object locative, e.g.  myverb__loc1__loc2 ?

A way to think of it is this. In the construct   myverb__mylocptr , the locative designation mylocptr can itself be an object locative (in this case  loc1__loc2). This feature is illustrated in the example of a doubly-linked queue below.

At any given moment, J recognizes an implied locale, which is the first public namespace J looks inside for the entity in question.

If a private namespace is active, references to non-locatives will look there before trying public namespaces.

If J can't find the entity in the implied locale, it looks inside the locales in its search path. Each locale has its own search path, which can be changed during execution as described below.

Note: The J Dictionary uses the term current locale instead of implied locale. We shall use both here, with current locale serving to emphasize what is seen when the J interpreter is idle.

At startup, the implied locale is the base locale.

The implied locale can change many times during execution of a sentence, as described further down this page.


An example using explicit and object locatives

Make a script containing the code

make=: verb define
  NB. make doubly-linked queue of (y) numbered locales
  locs=. cocreate@''@>i.y
  for_loc. locs do.
    name__loc=: 'This is locale ',;loc
    prev__loc=: locs {~ y|loc_index-1
    next__loc=: locs {~ y|loc_index+1
  end.
)

Numbered locales are different from named locales in that they must be explicitly created before using. This verb conew 'classname' will create a numbered locale as an instance of the class classname. The verb cocreate'', reraely used, creates a numbered locale that is not an instance of any class.

inspect=: verb define
NB. inspect contents of numbered locale (y)
  cocurrent ": y
  echo '----------'
  echo names'' [ smoutput 'contents of locale: ' , ": y
  echo name [ smoutput 'name:'
  echo prev [ smoutput 'prev:'
  echo next [ smoutput 'next:'
)

inspec2=: verb define
NB. inspect contents of numbered locale (y)
NB. Use object locatives instead of: cocurrent''
  loc=. < ": y
  echo '----------'
  echo names__loc'' [ smoutput 'contents of locale: ' , ": y
  echo name__loc [ smoutput 'name:'
  echo prev__loc [ smoutput 'prev:'
  echo next__loc [ smoutput 'next:'
)

Verbs inspect and inspec2 give identical results, but by different means.

Make a queue of 5 objects and inspect object 3

   make 5
┌─┐
│0│
└─┘
   inspect 3
----------
contents of locale: 3
name next prev
name:
This is locale 3
prev:
+-+
|2|
+-+
next:
+-+
|4|
+-+
   coname''
+----+
|base|
+----+
   name_3_   NB. explicit locative
This is locale 3

Notice that when inspect exits, J restores the implied locale to base without your code having to do this, as we show by  coname'' .

Notice too that you don't have to use an object locative to access entities inside a numbered locale. You can use an explicit locative instead, e.g.  name_3_ . But it is harder to write code to manipulate a multiplicity of similar locales, which is where an (alterable) object locative has the advantage.

Choose an arbitrary object to be the head of the queue and create a noun: head to point to it:

  • Just like next and prev in any given object, the value of head is a boxed string of digits.
  • head will be used to form an object locative to refer to the contents of a given object.
  • By varying the value of head you effectively rotate the queue.
   head=: <,'3'
   name__head   NB. object locative: the value of (name) in locale 3
This is locale 3
   next__head   NB. object locative: the value of (next) in locale 3
+-+
|4|
+-+
   prev__head
+-+
|2|
+-+

Using multiple locale names in an object locative, it's possible to "reach" along the queue in either direction

   name__next__head
This is locale 4
   name__next__next__head
This is locale 0
   name__next__next__next__head
This is locale 1
   name__prev__head
This is locale 2
   name__prev__prev__head
This is locale 1


Name lookup and search paths

Name lookup begins with a simple name and a starting locale. If the original name was a locative, it gives the starting locale; otherwise J starts searching for the definition in the implied locale.

Namespaces are searched in the following order. If any search step succeeds, the search ends, returning the value that was found:

  1. Simple names in a sentence from an explicit entity will be sought in the private namespace of that entity. To be in the private namespace, the name must be assigned using =. rather than =:.
    The details get tricky when an explicit verb executes a tacit verb and you wonder just what names the tacit verb has access to. In that case you need the full rule, which is: If the original name was not a locative, and a private namespace exists (in otherwords, if an explicit entity is running), the youngest private namespace is searched to see if the simple name is defined there.
  2. The starting locale is searched.
  3. The locales in the search path of the starting locale are searched, one by one, stopping at the first successful search.

The search path of a locale is an ordered list of boxed locale names, which is initialized when a locale is created.
Note that a locale's search path does not include the locale itself.
Note also that the search paths of other locales are not used. The search path is a list, not a tree.

When a locale is created implicitly by reference, its search path initially includes only the z locale. An instance locale created by conew is given the search path of its class.

You can modify the search path with the copath and coinsert verbs.

Bypassing the Search Path: Nameref Caching

While most named nouns are local to the explicit definition they are used in, most named verbs are in public namespaces and require a lookup. If your search paths are long, the time spent looking up names can be noticeable. Nameref caching is a way to reduce the number of lookups of non-nouns.

Nameref caching is useful when your verbs do not change during execution. Most scripts do not create public verbs as they execute, And can profitably be loaded with nameref caching enabled. To turn on nameref caching for a script, simply write

9!:5 (1)

near the top of the script. Nameref caching will be enabled for all namerefs in that one script.
For compatibility with earlier versions of J you can use ". :: 1: '9!:5 (1)'

A nameref is a word that refers to a named value. It can be inside an explicit definition or in an executed sentence. When nameref caching is enabled, namerefs are marked as cachable when they are first encountered: for names in an executed sentence, that is when the nameref is parsed; for namerefs in an explicit definition, it is when the explicit definition is processed to produce a verb/adverb/conjunction (i. e. before the first execution of the body of the definition).

Because caching can properly apply only to non-changing public non-nouns, the following types of nameref are not cachable:

  • argument names x y u v m n u. v.
  • indirect locatives
  • name references created by 'name'~
  • in explicit definitions, any nameref to a name that is privately assigned in the definition

When a cachable nameref is looked up during execution, it value is used as usual, but the value is cached provided:

  • the value is not a noun
  • the value is stored in a named locale

Once the value is cached, it is used for all subsequent executions of that nameref.

Note: caching applies to individual namerefs. If several namerefs have the same name, their caching is independent.

If a name whose value has been cached in a nameref is modified or deleted, the old value is not deleted and continues to occupy space, and will still be used whenever the nameref is executed.

Example script:

9!:5 (1)  NB. Turn on nameref caching

debjoin =: deb@,   NB. concatenate, then delete blanks

ispalindrome =: 3 : 0   NB. Return 1 if the string y is a palindrome
nb =. deb y  NB. delete extra blanks
nb =. tolower nb  NB. convert to lowercase
nb -: |. nb  NB. see if string is the same left-toright and right-to-left
)

In this script, the cachable names are indicated in boldface. The names that are being assigned are not cachable because they do not refer to a value, and the final nb is not cachable because it refers to a name that is assigned inside the definition. The 3 cachable namerefs, to deb , deb, and tolower, will be found in z locale the first time the containing verb is executed, and will not be looked up again.


Nameref Caching with Numbered Locales and Search Paths

Object-oriented code, which uses numbered locales to distinguish objects that are operated on by the same code, does not fit the model of nameref caching if the search paths select a version of a verb to be executed.

Example: the verb optionverb is executed in a numbered locale. In a simple system, the name will be looked up and usually found in the named locale of the class for the object. This would be perfectly fine as a cached nameref, because each numbered locale would want to use the same cached definition.

But if search paths are used so that different numbered locales select different version of optionverb to execute, nameref caching would not work. That's a shame, because it is exactly the longest search paths that benefit most from caching.

There is a solution in the common case where the lookup does not change during the life of the numbered locale: explicitly create a reference in the numbered locale for each multi-version verb. The reference in the numbered locale will be cached, but will be kept separate from references in other numbered locales. For each reference, you will have just ono lookup in the numbered locale rather than a sequence of lookups through the path.

Put the following verb into your code somewhere:

NB. Create cached references in the implied (usually numbered) locale, for all
NB. non-nouns found in the search path stopping before the locale given in y
NB. y is a string, possibly boxed
NB. result is i. 0 0
NB. side-effect: names defined in implied locale
createcachedrefsfrompathuntil_z_ =: {{
path =. (copath coname'') (i. {. [) ,L:0 boxopen y  NB. locales to search in
vnm =. ~. ;@:(<@{{ (#~  1 2 3 e.~ 4!:0) nl__y '' }}"0) path  NB. names of unique non-nouns in path
for_nm. vnm do. (nm) =: nm 4!:8 end.  NB. Create a cover for each verb, in implied locale
i. 0 0
}}

In the create verb for the class, which initializes each numbered locale, insert the following somewhere after the path for the numbered locale has been set:

createcachedrefsfrompathuntil fixedlocale

where fixedlocale is the name of a locale in the path that does not contain any definitions of multiversioned verbs. Use can use z locale if there is none earlier in the path.

createcachedrefsfrompathuntil uses 4!:8 to create a reference in the numbered locale to each verb defined before fixedlocale.

Assignment

An assignment (using =. or =:) defines a name. The namespace in which the name is defined is given as follows:

1. If the assigned name is a locative, the name is defined in the starting locale. 1. Otherwise, if the assignment word is =. and a private namespace exists, the name is defined in the youngest private namespace. 1. Otherwise, the name is defined in the implied locale.


Changing the implied locale

The implied locale changes whenever one of these things happen

  1. executing cocurrent or coclass
  2. executing 18!:4 directly, which is deprecated because it has performance repercussions until the current named entity completes
  3. executing a locative
  4. exiting/returning from a named verb or modifier.
    Returning from an anonymous verb, even an explicit one, does not restore the implied locale.

Note: coclass has the same definition as cocurrent, but is used in a script to signify the start of an object-oriented class.

By 1. above, whether it is executed inside the body of a verb, or in immediate mode (i.e. in the J session)

   cocurrent 'mylocale'

makes mylocale the implied locale for subsequent J sentences.

By 3. above, before J starts executing a locative, it switches the implied locale to the starting locale written-into the locative. Then, by 3. above,it switches it back again. For example

   names 3

lists all verbs residing in the current locale, which we imagine here to be the base locale. But

   names_mylocale_ 3

lists all verbs residing in mylocale. This works even though mylocale may happen not to contain a verb called names.

The library verb names resides in the z-locale – and that's where J finds it in the above example. But after exiting verb names, J goes back to the existing implied locale, viz. base.

Note: The implied locale is always set to the starting locale written-into the locative, even if the simple name was found in some other locale in the search path.

For a worked example relying on this feature, see below: How to work with locales and locatives.

When a named explicit verb, or indeed any named entity exits/returns, the implied locale is set to what it was before the verb started running.

This means that when you execute a named verb, even with a locative, you can be sure the implied locale will be restored when the verb finishes.

WARNING: You can defeat this feature by calling  18!:4 directly, not via its cover name: cocurrent. Therefore avoid  18!:4 in favor of cocurrent.


How to work with locales and locatives

A small utility you've written for yourself can conveniently be loaded into the base locale, especially if it consists of just one verb. But a professionally written J application, e.g. an addon, generally creates one or more locales for its own use, e.g. to house its working code. Furthermore it may create additional locales (typically: numbered ones) as needed to implement (object-oriented) instances of any classes it employs.

Example: the J6.02 IDE implements multiple edit windows in this manner.


Example: writing your first professional-looking application

NB. Script: MyFirstApp
NB. Provides a single verb: sum
NB. It's meant to be used like this:
NB.       sum 1 2 3
NB.    6

sum =: +/

This utility loads into the implied locale, which by default is the base locale.

But do you want to clutter your user's base locale with secret words which are not of her making?
No...

So you arrange to load your simple app into the z-locale instead of the base locale. This still makes it visible inside the base locale, indeed any locale at all

NB. Script: MySecondApp
NB. Provides a single verb: sum
NB. It's meant to be used like this:
NB.       sum 1 2 3
NB.    6

sum_z_ =: +/

But do you want to clutter the z-locale with words of significance only within the guts of your app, risking name-clashes which overwrite standard library words which your user needs?
No...

One or two new z-words are okay, but they ought to be public words, which you instruct your user to call.

So you arrange to load your simple app into its own private locale instead of the z-locale. This hides your working code out of harm's way

NB. Script: MyThirdApp
NB. Provides a single verb: sum
NB. It's meant to be used like this:
NB.       sum 1 2 3
NB.    6

coclass 'MyThirdApp'
NB. All names assigned from here on are defined in the locale MyThirdApp

sum =: +/

But your user is still not happy. She now has to call your utility like this:

   sum_MyThirdApp_ 1 2 3
6

It's not as convenient as

   sum 1 2 3

So you arrange to load a single word into the z-locale as well, which gives your user a convenient handle to work with your app

NB. Script: MyFourthApp
NB. Provides a single verb: sum
NB. It's meant to be used like this:
NB.       sum 1 2 3
NB.    6

coclass 'MyFourthApp'

sum =: +/

NB. The public interface to MyFourthApp
sum_z_ =: sum_MyFourthApp_

Now you have reproduced the structure of a typical professionally written application.

Let's go back to that last definition: sum_z_ =: sum_MyFourthApp_. How did that let the user write

   sum 1 2 3

and have it executed in the correct locale?

There were two steps to executing sum 1 2 3.

1. The verb, sum, was looked up starting in the user's locale. It wasn't found there, so the search proceeded until the name was found in z locale. The name sum has the verb value sum_MyFourthApp_, so it is replaced by its value. No change of locale is performed, because looking up a name doesn't change the locale, no matter where the name is found. 1. Now the interpreter executes sum_MyFourthApp_ 1 2 3. This is the execution of a locative, so the implied locale is changed before executing the body of sum.


Example: how addon: 'general/dirtrees' uses locales and locatives

The addon: general/dirtrees provides two utility verbs: copytree and deltree. These enable you to copy and delete folders on disk, together with their contents.

The working code resides in two locales: rgsdirtrees and rgsdirutils, as you can see

   conames''   NB. what locales are present to start with?
base      ctag      j         jadetag   jcompare  jp        jqtide
jregex    jrx       jtask     qtprinter z

   load 'general/dirtrees'

   conames''   NB. NOW what locales are present?
base        ctag        j           jadetag     jcompare    jp
jqtide      jregex      jrx         jtask       qtprinter   rgsdirtrees
rgsdirutils z

Run copytree, using a stock example

   SRCDIR=: jpath '~tools'
   TRGDIR=: jpath '~temp/tools'
   TRGDIR copytree SRCDIR   NB. copy source directory SRCDIR into ~temp
2 2
   deltree TRGDIR   NB. delete the folder we've just made and all its contents
1
   deltree TRGDIR   NB. delete it again -- response 0 means it isn't there any more
0

That all works fine. Verbs copytree and deltree weren't visible before, but they are now.

Take copytree. You can view its definition

   copytree
copytree_rgsdirtrees_

...but where does it reside? Not in the current locale, which only contains the two nouns we've defined: SRCDIR and TRGDIR

   coname''    NB. What is the current locale?
+----+
|base|
+----+
   names''
SRCDIR TRGDIR

It happens to be in the z-locale, as you can see

   names_z_''
ARGV                BINPATH             CR                  CRLF
Cut                 DEL                 Debug               EAV
...
...
   NB. not recommended, because the list is rather big !!
   'cop' names_z_''   NB. what are the words in z-locale beginning with 'cop' ?
copath   copytree

How did addon: general/dirtrees manage this trick? You can view its script, like this

   open 'general/dirtrees'

or, more reliably, like this

   open '~addons/general/dirtrees/dirtrees.ijs'

The last two lines happen to be

copytree_z_=: copytree_rgsdirtrees_
deltree_z_=: deltree_rgsdirtrees_

If we look at locale rgsdirtrees we see it contains only three words

   names_rgsdirtrees_ ''
copytree deltree  fcopy

but these are the heart of the dirtrees addon.


Working with classes and instances

You can use a locale as an object-oriented class instance. The locale serves as a separate namespace for the instance.

See Studio/Locales for the best available description of how to write an object-oriented class, and create instances of that class. What follows is the barest outline of how to go about it.

To make a class supporting instances:

  • Create a named locale e.g. myClass that will contain the common code plus any data shared by all the class instances. This locale is the class.
  • Within this locale, define two verbs: create and destroy (the names are mandatory), to be executed as the first and last steps in the career of a class instance
    • There are subtleties in the operation of create and destroy. See the lab above, or carefully follow a working example. The use of f. to refer to the shared class rather than the instance is essential.
    • The instance to be destroyed may own resources, such as window, which it needs to release.
    • The last line of destroy should be the sentence:  codestroy''
  • Place any information needed to create the given class instance in a noun e.g. InitializingInfo.

Now you can create an instance of myClass as follows

   TheInst =: InitializingInfo conew 'myClass'

This creates a new numbered locale, whose search path is altered to include the shared namespace: myClass. (It already includes the namespace: z.)

This new locale is the class instance.

The id of this locale (a boxed string of digits) gets assigned to a noun: TheInst, where you can later refer to it, e.g. to destroy the instance.

  • To access a noun: myAttr belonging to the instance, use the object locative:  myAttr__TheInst .
  • Likewise, to run a verb: myMethod belonging to the instance, use the object locative:  myMethod__TheInst y .
  • Alternatively, if you discover the value of TheInst is  <,'4' say, (signifying 4 is the "number" of the numbered locale) then you can refer to these two entities like this:
    • myAttr_4_
    • myMethod_4_ y
  • To destroy the instance call:  destroy__TheInst''

The only thing that makes the new instance an instance of myClass (rather than some other class) is its search path. conew sets the search path in the new instance to include the locale of the class, followed by any other locales in the class's search path, followed by z.


Numbered locales

The locales created by conew are numbered rather than named, so that they will never collide with names you invent for your entities.

A numbered locale behaves just like a named locale: its name is a string (of digits). You can use it in either kind of locative to refer to words residing inside the locale.

Actually, numbered locales have the same features as named locales, but they are designed to use less memory.

This avoids having to invent a name for each new locale, or even bother finding the next available number, bearing in mind that id numbers of destroyed class instances can't be reused.

You can use the same technique yourself to create and manage multiple instances of your own classes.

Note: A numbered locale can also be specified as an atomic integer. Doing so will save the cost of converting a string to an integer every time the locale is referenced. The simplest way to do this is to convert the value returned by conew as soon as you can:

obj =: 0&".@> conew parameters


Class Verbs and Instance Verbs

The verbs of a class are defined in the locale of the class. Since this locale is the first locale in the search path of the instance, references to such verbs from an instance will be found in the class, but the implied locale will remain in the instance; thus, public assignments will happen in the instance rather than in the class. These verbs are called instance verbs. Most verbs in a class using instances are instance verbs.

Class verbs are verbs that are called from an instance but need to execute in the locale of the class, usually because they need to use a shared class resource. For example, you might want to keep a list of all instances that have been created, so that you can destroy them when the program exits. This list would belong to the class rather than to any instance.

To make a verb a class verb, you execute it in the class locale rather than the instance locale, using a locative to make the switch. Thus,

   classverb_myClass_ mydata

will switch the locale to myClass before executing classverb. Note that mydata is evaluated in the instance's locale, not in the class locale.

To make sure that a name is always used as a class verb, you can build a locale-switch into the name:

   classverbA =: verb define  NB. This name will never be used outside this definition
...
)
   classverb =: classverbA_myClass_

Now any use of classverb will run in the class, not the instance.


Inheritance

A class A inherits names (which may include nouns and verbs) from class B by having class B in the search path of A. Then, an instance of A will automatically have access to the values in class B. If class A defines any names also used in B, A's values will override B's.

You inherit from a class by executing

   coinsert 'parentclass'

usually right after the coclass that started the class. coinsert inserts parentclass, followed by its entire search path, into the search path of the implied locale. The newly-inserted items go to the end of the search path, except for z locale which stays at the very end.

Multiple Inheritance

When you inherit from a parent, you automatically inherit from its parents, since its entire search path becomes included in yours.

You may inherit from multiple parents by coinserting them. You may also pick and choose which locales to inherit from by building your own custom search path.


Deleting a locale

Delete a named locale with

 coerase <'locale-name'

It is unusual to delete a named locale, since it contains only verbs and shared data.

Deleting an instance locale, on the other hand, is a vital part of any programs using objects. To ensure proper deletion of all resources, destroy an object with

 destroy__instance-name optional parameters

Do not use coerase on an instance. Doing so may leave resources unfreed.

It is OK to delete a locale while it is running. The final deletion will take place when the locale comes out of execution.

If you delete the current locale that your typed sentence was running in, when that sentence finishes there will be no implied locale and no search path. That is not an error, but you will be typing into a bare JE, with no names defined and with no namespace for you to assign names in.

Verbs Relating To Locales

x

(if any)

name y Function
coclass

cocurrent

locale name (a character string, either boxed or unboxed) Sets the implied locale to y. The implied locale will revert when a named entity finishes execution.
optional creation parameters conew class name (a locale name, as an unboxed character string) Creates an instance of the class y, sets the search path of the new instance to include the locale y followed by the search path of y, and sets COCREATOR in the instance to the name of the locale that it was created from. If x is given, executes create x in the instance, passing the parameters into the create verb. The result of conew is the name of the generated instance locale, a boxed string.
codestroy '' Destroys the currently-active locale, after it has finished execution.
coname '' The name of the implied locale, a boxed character string.
copath locale name (a character string, either boxed or unboxed) Returns the search path for the locale y - a list of boxed locale names. Use copath coname '' to find the search path of the implied locale.
new search path (a list of boxed locale names or a single unboxed locale name) copath locale name (a character string, either boxed or unboxed) Sets the search path of y to x. Normally the search path will end with z locale.
coinsert list of locale names, either as a boxed list or as a character list containing space-separated locale names The search paths of all the locales in y (each augmented by having the starting locale from y added to the beginning) are concatenated together (in the order given) and added onto the end of the search path of the implied locale. Any occurrence of z locale is moved to the very end of the search path.

Example: If the search path of the implied locale is A,B,z, the search path of locale m is C,D,z, and the search path of locale n is E,z, then executing
   coinsert 'm n'
will change the search path of the implied locale to A,B,m,C,D,n,E,z

optional value specifying the size of the name table cocreate locale name (a character string, either boxed or unboxed) or '' If y is empty, creates a numbered instance locale. Otherwise, creates the locale named y.
conl list specifying the locales to name Returns a boxed list of active locales. If y is empty or contains 0, named locales are included; if y is empty or contains 1, numbered locales are included.
conames list specifying the locales to name like conl, but formats the result into columns
cofullname a name, either boxed or unboxed Returns a character list containing a locative for the name. If the original name was a locative, it is unchanged; otherwise the name of the implied locale is appended.
coerase a boxed locale name Destroys locale y after it finishes execution.
coreset '' Destroys all instance locales after they have finished execution.

Adverbs in Locales

Consider this example:

adv_example_=:1 :0
  echo coname ''
  u y
)

When we try this out, we are not in the example locale but instead are in the base locale:

   - adv_example_ 3
┌────┐
│base│
└────┘
_3

What happened here?

The issue is that this adverb returns an anonymous explicit verb during the evaluation of - adv_example_ so it loses track of the original locale before it sees the value 3.

To work around this issue, we must keep track of the locale ourselves:

adv_example_=: 1 :0
  u adv_implementation_example_ (coname)
)
adv_implementation_example_=: 2 :0
  return_locale=. coname
  cocurrent v
  echo coname
  return_value=. u y
  cocurrent return_locale
  return_value
)

Note that names with _ in them which do not have a trailing _ are not locatives.

Note that we are still working with an anonymous verb here, and the automatic "switch back to previous locale" feature of 18!:4 only happens when executing named code. So we must manually switch back, ourselves (and must also switch back at the command line if we get an error in the switched code).