Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate new unique name for context?

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)?

like image 206
Alexey Popkov Avatar asked Jul 28 '11 14:07

Alexey Popkov


3 Answers

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[], "-" -> ""]~~
  "`"
like image 78
WReach Avatar answered Sep 20 '22 00:09

WReach


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.

like image 36
Leonid Shifrin Avatar answered Sep 21 '22 00:09

Leonid Shifrin


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.

like image 44
Sjoerd C. de Vries Avatar answered Sep 20 '22 00:09

Sjoerd C. de Vries