If you have old version of Caché, you can use %ZEN.Auxiliary.jsonProvider or %ZEN.Auxiliary.altJSONProvider, which have a bunch of useful methods, for example:
%ArrayToJSON
%WriteJSONFromArray
%WriteJSONStreamFromArray
etc.

Here are two small examples:

set array=##class(%ListOfDataTypes).%New()
for i=1:1:4000000 array.Insert("item"_i)
   
write "count = ",array.Count(),!
   
do ##class(%ZEN.Auxiliary.altJSONProvider).%WriteJSONStreamFromObject(.stream,array,,,1,"aeloq")
   
; here you can save stream to a file or send it to the client
set meta=$lb("nameA","nameB","nameC")
   
for i=1:1:4000000 set data(i)=$lb("itemA"_i,"itemB"_i,"itemC"_i)
   
do ##class(%ZEN.Auxiliary.altJSONProvider).%ArrayToJSON(.meta,.data)

To Dmitry's words I will add a few links from the documentation:

In your case, be the $LISTTOSTRING function is useful, for example:

USER>set first=$lb("words","more","words")
USER>write first
words-morewords
USER>write $listtostring(first)
words,more,words
USER>write $listtostring(first,"^")
words^more^words
USER>write $listtostring(first,"")
wordsmorewords

I think that the result of "dogcatfish" in the book was due to copying/pasting, which caused the service characters to be lost.

By the way, here on the forum it’s also not so easy to insert this gibberish ;)

 
And more food for thought:

Hi Peter.

Ok.

"Time for If (i=2): ",time(2,"end")-time(2,"start")," seconds",!,
  "Time for ElseIf #1 (i=3): ",time(3,"end")-time(3,"start")," seconds",!,
  "Time for ElseIf #2 (i=1): ",time(1,"end")-time(1,"start")," seconds",!,
  "Time for Else (i=4): ",time(4,"end")-time(4,"start")," seconds",!!

1e6
Time for If (i=2): .030974 seconds
Time for ElseIf #1 (i=3): .045126 seconds
Time for ElseIf #2 (i=1): .07144 seconds
Time for Else (i=4): .087353 seconds

1e9
Time for If (i=2): 28.59286 seconds
Time for ElseIf #1 (i=3): 43.044261 seconds
Time for ElseIf #2 (i=1): 82.277535 seconds
Time for Else (i=4): 69.212718 seconds

I have (2019.1.1CE) this is not confirmed:

i=1:1:4 {
  time(i,"start")=$zh
  f j=1:1:1e6 {
      i=2 {
        a=2
      ElseIf i=3 {
        a=3
      ElseIf i=1 {
        a=1
      Else {
        a=0
      }
  }
  time(i,"end")=$zh
}

"Time for If (i=2): ",time(1,"end")-time(1,"start")," seconds",!,
  "Time for ElseIf #1 (i=3): ",time(2,"end")-time(2,"start")," seconds",!,
  "Time for ElseIf #2 (i=1): ",time(3,"end")-time(3,"start")," seconds",!,
  "Time for Else (i=4): ",time(4,"end")-time(4,"start")," seconds",!

Time for If (i=2): .109283 seconds
Time for ElseIf #1 (i=3): .060785 seconds
Time for ElseIf #2 (i=1): .08026 seconds
Time for Else (i=4): .109974 seconds

Hi Nigel.

I hasten to inform you that new classes have been added to IRIS for writing/reading streams in JSON format: %Stream.DynamicBinary, %Stream.DynamicCharacter.

 

Here is a sample code:

Result:

USER>##class(dc.test).test()
[Export] len(string): 3641129, len(cs): 7282288
 
1. [Import    %DynamicObject] len(longstring): 3641129, len(cstream): 7282288
2. [Import %RegisteredObject] len(string): 3641129, len(cs): 7282288
3. [Import %RegisteredObject] len(string): 3641129, len(cs): 7282288

Patch for 2019.1.1CE:

Instead of

        $$$GENERATE(indent_"  Set sc=stream.Write(%JSONObject."_$$$QN($$$jsonfieldname(propertyMap))_") If $$$ISERR(sc) Goto %JSONImportExit")

need

        $$$GENERATE(indent_"  Set testInvalidField=0, sc=stream.CopyFrom(%JSONObject.%Get(field,,""stream"")) If $$$ISERR(sc) Goto %JSONImportExit")

It is possible that in version 2019.4.x has already fixed everything.

The example below works even in Caché:

#include %systemInclude n try{   $$$AddAllRoleTemporaryInTry   n $namespace   s $namespace="SAMPLES"      person=##class(Sample.Person).%OpenId(1)      ##class(%ZEN.Auxiliary.altJSONProvider).%WriteJSONStreamFromObject(.stream,person,,,$$$YES,"aeloq")   "json (string): ",stream.Read($$$MaxLocalLength),!!      ##class(%ZEN.Auxiliary.altJSONProvider).%ConvertJSONToObject(stream,"Sample.Person",.obj)   "obj.Home.Street: ",obj.Home.Street ; or d $system.OBJ.Dump(obj)    }catch(ex){   "Error "ex.DisplayString(),! }
Result: USER>^test json (string): {"Name":"Pascal,Martin F.","SSN":"502-68-5767","DOB":43307,"Home":{"Street":"9347 Franklin Drive","City":"Denver","State":"VA","Zip":66346},"Office":{"Street":"4897 Main Blvd","City":"Miami","State":"MO","Zip":60084},"Spouse":"","FavoriteColors":[],"Age":"60"} obj.Home.Street: 9347 Franklin Drive

Or use %JSON.Adaptor: Exporting and Importing

See answer by @Brendan Bannon about TuneTable.

Documentation:

“Relative cost” is an integer value which is computed from many factors as an abstract number for comparing the efficiency of different execution plans for the same query. This calculation takes into account (among other factors) the complexity of the query, the presence of indices, and the size of the table(s). Relative cost is not useful for comparing two different queries. proof

Could you cite the test code for $$select^LVBEPVIS and run it from a VBScript program from Windows Explorer.
Also give your $zv (interested primarily in 8-bit or Unicode).

My test for the Caché Unicode:

LVBEPVIS.MAC:
select(n)   PLIST=4   PLIST(1)="018625110"   PLIST(2)="01862511"_$c(9,233,769)   PLIST(3)="F"_$c(1)_"Female"_$c(1)_"Y"   PLIST(4)=35633   1
test.vbs:
Set AxVisM1 = CreateObject("VISM.VisMCtrl.1") AxVisM1.Server="CN_IPTCP:localhost[1972]:_system:@SYS" AxVisM1.NameSpace="USER" AxVisM1.Execute("s err="""",err=$$select^LVBEPVIS(""018625110"")") WScript.Echo AxVisM1.PLIST
Result:

Example with one file for Windows:

Class dc.test Abstract ]
{

/// d ##class(dc.test).test()
ClassMethod test()
{
  ts=##class(%PosixTime).LogicalToUnixTime(##class(%PosixTime).CurrentUTCTimeStamp()),
    oldName="C:\Tmp\test",
    newName=oldName_$$$FormatText("a%1.txt",ts)
  
  f=##class(%Stream.FileBinary).%New()
  f.LinkToFile(oldName)
  
  gz=##class(%Stream.FileBinaryGzip).%New()
  gz.Filename=newName
  gz.CopyFromAndSave(f)

  ##class(%File).Delete(oldName)
}

}

@Julius Kavay got a point.

I will offer two more options:


Class ABC.Try
{

/// d ##class(ABC.Try).PackageExists()
ClassMethod PackageExists(package "ABC")
{
  ; option by Julius Kavay
  list=##class(%Dictionary.PackageDefinition).GetPackageList()
  ''list.Find($zcvt(package,"U")),!
  
  ; option 2
  ##class(%Library.RoutineMgr).Exists($zcvt(package,"U")_".PKG"),!
  
  ; option 3
  list
  d $system.OBJ.GetPackageList(.list,package)
  ''$d(list),!
}

}

USER>##class(ABC.Try).PackageExists("ab")
0
0
0
 
USER>##class(ABC.Try).PackageExists("abc")
1
1
1

UPD:
Take another look at the %Dictionary.PackageDefinitionQuery:SubPackage/FlatPackage, %ZEN.Utils:EnumeratePackages