开发者

How to generate new unique name for context?

开发者 https://www.devze.com 2023-03-23 18:57 出处:网络
What is the best way to generate a name for some temporary context which is guaranteed to be unique (开发者_运维问答context with this name must not exist in the system)?The following expression will g

What is the best way to generate a name for some temporary context which is guaranteed to be unique (开发者_运维问答context with this name must not exist in the system)?


The following expression will generate a context name that is guaranteed not to conflict with any loaded context:

First@Contexts[] //.
  c_ /; MemberQ[Contexts[], c] :>
    "Context"~~ToString[RandomInteger[1000000]]~~"`"

It makes no attempt to account for contexts that are not yet loaded. As written, this expression could be used up to 1,000,000 times before running out of names. Adjust the fixed string ("Context") and name count (1000000) to suit your taste.

Update

As @Leonid points out in a comment, empty contexts will not be listed in Contexts[]. Therefore, it is strictly speaking possible that this expression could return the name of an existing empty context.

UUIDs

For all practical purposes, generating a name from a number randomly selected from a large enough range would work, e.g.

"Context"~~ToString[RandomInteger[2^128]]~~"`"

In a similar vein, one could use a UUID. UUIDs are routinely used as identifiers that are phenomenally likely to be unique across all network nodes as well:

Needs["JLink`"]
LoadJavaClass["java.util.UUID"]

"Context"~~
  StringReplace[JavaBlock@java`util`UUID`randomUUID[]@toString[], "-" -> ""]~~
  "`"


I can suggest a function I used here:

Clear[unique];
unique[sym_] :=
ToExpression[
   ToString[Unique[sym]] <> 
      StringReplace[StringJoin[ToString /@ Date[]], "." :> ""]];

You can replace the ToExpression by StringJoin[...,"`"] to tailor it to your needs.


Another option would be to look at all starting contexts (before the first backquote), find their string length and then generate a string (maybe random, but that isn't necessary) that is at least one character longer than the others. This is guaranteed to be unique, and there isn't even a theoretical possibility of a collision as in some of the other solutions.

sl = (StringSplit[#, "`"][[1]] & /@ Contexts[] // StringLength // Max )

Out[349]= 30

In[353]:= "c" ~~ ToString[10^sl] ~~ "`"

Out[353]= "c1000000000000000000000000000000`"

A disadvantage of this method would be that the context names get longer after each repeated application of this method. ;-) If that's a problem we could create a unique name based on the set of longest context names using Cantor's diagonal procedure.


Is Unique perhaps what you're looking for?


This is really an example illustrating Alexey's response to Sjoerd's answer/question. From a fresh kernel on my machine, the following code

Begin["myContext3`"];
Unique["myContext"]

Yields "myContext3". Thus, clearly, Unique (the first thing I thought of) does not work.

Incidentally, I would have just added a comment to Sjoerd's response, but I don't know how to include the accent symbol used to denote a context inline. Does anyone here know how to do this?

0

精彩评论

暂无评论...
验证码 换一张
取 消