My first ⎕CSE program - "Hello World"

General discussions related to using the C# Script Engine in APL+Win.

Moderators: Tech Support, phpbb_admin

My first ⎕CSE program - "Hello World"

Postby brent hildebrand » November 11th, 2014, 2:30 pm

One APLer's view of C#

Here are some defintion of terms from my point of view. I may not have everything correct yet, this is my start in the ⎕CSE world.

A Method is to C# what a user Function is to APL. Methods always have parenthesis. A niladic APL function, Foo, equivalent in C# would be, Foo()

A Property is to C# what a Variable is to APL. Properties in the C# world can be of many different kinds.

A Namespace is to C# what a Workspace is to APL.

An expression is to C# what a statement is to APL.

The semi-colon in C# marks the end of an expression and must be present.

The semi-colon also acts like an APL diamond, allowing the placement of multiple expressions on a single line
C#: expression; expression; expression;
APL: statement ⋄ statement ⋄ statement

While C# programs can be written on a single line, they are often broken up and indented to show the thought and flow of the program. This is the same as APL!

C# is always index 0.

C# can reference Methods and Properties in other Namespaces. Those references must be declared. APL would need to copy in the Functions and Variables from another workspace or component file in order to use them. These need to be declared in the reference section in Visual Studio. In APL, these are the arguments to the "Init" method of ⎕CSE.

C# is object oriented, and certain namespaces use object in other namespaces, so both must be referenced.

Using ⎕CSE in APL, the arguments of the "Init" Method are the references to the .NET Namespaces that will be referenced in the C# code. This is analogous to the Reference section in the Solution Explorer in Visual Studio.

"using" statements in C# create shorter names to objects in other Namespaces. These are optional, but make writing code easier/shorter.

My first APL/⎕CSE program - Spoken "Hello World"

Code: Select all
ret←larg CSSpeak text;s;sink
:if ⎕dyadic ⍝ used only to redefine the ⎕cse instance when adding new code
    'Speak' ⎕cse 'Close'
:end

:if~(⊂⎕cself←'Speak')∊'#'⎕cse'instances'
    ⎕cself←'Speak' ⎕cse 'Init' 'System' 'System.Speech'
    ret←⎕cse'returnonerror'1

    s←⊂'using System;'
    s,←⊂'using System.Speech.Synthesis;'
    s,←⊂'SpeechSynthesizer synth = new SpeechSynthesizer();'
    s,←⊂'synth.SetOutputToDefaultAudioDevice();'
    s←⎕cse 'Exec' (⊃s)
:end
⍝ret←⎕cse 'ExecStmt' ('synth.Speak("',text,'");') ⍝ play syncronously
ret←⎕cse 'ExecStmt' ('synth.SpeakAsync("',text,'");') ⍝ play asyncronously


The Namespace 'System.Speech' contains the System.Speech.Synthesis namespace and the using statement creates a shortcut to the SpeechSynthesizer, otherwise it would have needed to be called by typing System.Speech.Synthesis.SpeechSynthesize.
'System.Speech.Synthesis.SpeechSynthesizer synth = new System.Speech.Synthesis.SpeechSynthesizer();'
using simplifies this to:
'SpeechSynthesizer synth = new SpeechSynthesizer();'

CSSpeak 'Hello World'


Second ⎕CSE program:
Code: Select all
ret←larg CSPlayFile file;⎕cself;sink;csobj
csobj←⎕vget 'CSobj' 'Play'
:if ⎕dyadic
    ret←csobj ⎕cse 'Close'
    :returnif 0=⍴,file
:end

:if~(⊂⎕cself←csobj)∊'#'⎕cse'instances'
    ⎕cself←csobj ⎕cse 'Init' 'System' 'PresentationCore' 'WindowsBase'
    sink←⎕cse'returnonerror'1   
    sink←⎕cse 'ExecStmt' 'var player = new System.Windows.Media.MediaPlayer();'
:end
sink←⎕cse 'ExecStmt' ('player.Open(new System.Uri(@"',file,'"));')
ret←⎕cse 'ExecStmt' 'player.Play();'


CSPlayFile 'c:\windows\media\tada.wav'

The Uri Method is a member of the System Namespace. System.Windows.Media.MediaPlayer references both the PresentationCore and WindowsBase Namespaces and thus they must be "referenced" in the ⎕CSE "Init" method.

The .NET framework has thousands of methods in many different namespaces. The Object Explorer in Visual Studio is useful for finding how to reference a given method. And the Internet is helpful for finding out how to use the various methods, including places such as StackExchange.

I found the videos on C# for the Absolute Beginners to be very helpful.
http://channel9.msdn.com/Series/C-Funda ... -Beginners

I have not been able to write ⎕CSE code to access the console. The code seems to execute without error, but no concole window opens. ???
brent hildebrand
 
Posts: 479
Joined: February 12th, 2007, 5:53 pm
Location: Loma Linda, CA

Re: My first ⎕CSE program - "Hello World"

Postby Ajay Askoolum » November 12th, 2014, 3:01 am

Very good synopsis of how to move from APL jargon to C# jargon.

Try
Code: Select all
 Console.ReadLine();
to force the box to show & wait for you to press Enter.

Perhaps you have not explored this yet but when you have, add some supplementary notes on how scope works in C# (i.e. localization of variables in APL).

There is a lot of affinity between C# and APL - if the mind is willing, C# is very accessible for the APL programmer.
Ajay Askoolum
 
Posts: 636
Joined: February 22nd, 2007, 2:16 am
Location: United Kingdom

Re: My first ⎕CSE program - "Hello World"

Postby brent hildebrand » November 12th, 2014, 10:13 am

Ajay, my summary I know is incomplete and perhaps not completely accurate.

Scope - in C# variables and methods are as if they are all localized in APL, unless they are declared to be public. Public it to C# what Global is to APL.

I have not included in my personal summary the definition of a Class, how a class can inherit methods and properties, and how encapsulation affects scope. These terms fall under the subject of Object Oriented Programming.

Miscellaneous observation: Most classes in C# inherit a ToString() method which is like applying a Format/Tack in APL to a variable.

Variable type does not change in C# once declared, while in APL it can constantly change if one wishes.

Console: I have tried using Console.ReadLine();
brent hildebrand
 
Posts: 479
Joined: February 12th, 2007, 5:53 pm
Location: Loma Linda, CA

Re: My first ⎕CSE program - "Hello World"

Postby Ajay Askoolum » November 12th, 2014, 2:49 pm

I think the compiler behind []cse redirects Console Input/Output; perhaps Joe can confirm this.

ToString() does a lot more than APL thorn; e.g.

Code: Select all
       ⎕cse 'GetValue' 'Convert.ToString(12,8);'
14
      ⎕cse 'GetValue' 'Convert.ToString(912,16);'
390
      ⎕cse 'GetValue' 'Convert.ToString(12,2);'
1100
Ajay Askoolum
 
Posts: 636
Joined: February 22nd, 2007, 2:16 am
Location: United Kingdom

Re: My first ⎕CSE program - "Hello World"

Postby brent hildebrand » November 13th, 2014, 6:10 pm

ToString is overridden in a number of .NET classes. The Convert class has some interesting additions.

Console - it seems that only showing a visible console is excluded in []CSE. WriteLIne and ReadLine appear to be ignored by []CSE.
Code: Select all
ret←larg CSBeep text;s
⎕cself←'Beep' ⎕cse 'Init' 'Microsoft.CSharp'
ret←⎕cse'returnonerror'1
s←⊂'using System;'
s←,⊂'System.Console.Beep(880, 500);'
s,←⊂'System.Console.Beep(440, 500);'
s,←⊂'System.Console.Beep(880, 500);'
s,←⊂'System.Console.Beep(440, 500);'
s,←⊂'System.Console.WriteLine("Hello");'
s,←⊂'System.Console.ReadLine();'
s,←⊂'System.Console.Beep();'

s←⎕cse 'Exec' (⊃s)

'Beep' ⎕cse 'Close'
brent hildebrand
 
Posts: 479
Joined: February 12th, 2007, 5:53 pm
Location: Loma Linda, CA

Re: My first ⎕CSE program - "Hello World"

Postby Eric.Lescasse » November 14th, 2014, 8:48 pm

Brent,

There are also the System.Diagnostics.Process and System.Diagnostics.ProcessStartInfo classes which allow to open a DOS window and leave it opened or not.

I believe the same code could be used with other executables (just replace cmd.exe in the below code).

The following function shows how to use these classes:

Code: Select all
r←mode CSCmd args;s;z
⍝∇ r←mode CSCmd args -- Somewhat similar to ⎕cmd but can capture DOS command output
⍝∇ cmdArgs ←→ cmd.exe argument (i.e. 'dir *.sf')
⍝∇ mode ←→ ¯2= execute command with no window; return command output
⍝∇         ¯1= execute command with no window
⍝∇          0= execute command with window; close window when done
⍝∇          1= execute command with window; leave window opened
⍝∇ Examples:
⍝∇      ¯2 CSCmd'dir'
⍝∇       1 CSCmd'dir'
⍝∇       0 CSCmd'dir'
⍝∇      ¯1 CSCmd'dir'
⍝∇ ELE15nov14

r←0 0⍴''
:if~(⊂⎕cself←'cscmd')∊'#'⎕cse'instances'
    z←⎕cse'Init' 'System'
    z←⎕cse'returnonerror'1
    s←""
    s,←⊂"using System;"
    s,←⊂"using System.Diagnostics;"
    z←⎕cse'Exec'(⊃s)
:endif
s←''
s,←⊂"Process process = new Process();"
s,←⊂"ProcessStartInfo startInfo = new ProcessStartInfo();"
s,←⊂'startInfo.FileName = "cmd.exe";'
:if mode=¯2
    s,←⊂'startInfo.CreateNoWindow = true;'
    s,←⊂'startInfo.UseShellExecute = false;'
    s,←⊂'startInfo.RedirectStandardOutput = true;'
:endif
:if mode=¯1
    s,←⊂'startInfo.WindowStyle = ProcessWindowStyle.Hidden;'
:endif
s,←⊂'startInfo.Arguments = "/',('CK'[1+mode=1]),' ',args,'";'
s,←⊂'process.StartInfo = startInfo;'
s,←⊂'process.Start();'
:if mode=¯2
    s,←⊂'string result = process.StandardOutput.ReadToEnd();'
    s,←⊂'process.WaitForExit();'
:endif
z←⎕cse'Exec'(⎕←⊃s)
:if mode=¯2
    r←⎕tclf~⍨⎕cse'GetValue' 'result'
:endif


Here are some examples using it which show the C# code used:

Code: Select all
      1 CSCmd'dir'
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/K dir";
process.StartInfo = startInfo;
process.Start();
      0 CSCmd'dir'
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/C dir";
process.StartInfo = startInfo;
process.Start();
      ¯1 CSCmd'dir'
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.Arguments = "/C dir";
process.StartInfo = startInfo;
process.Start();
      ¯2 CSCmd'dir'
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.CreateNoWindow = true;
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
startInfo.Arguments = "/C dir";
process.StartInfo = startInfo;
process.Start();
string result = process.StandardOutput.ReadToEnd();
process.WaitForExit();
 Volume in drive D is DATAPART1
 Volume Serial Number is 4A53-7CE8

 Directory of D:\APLWIN14.2

05-Nov-14  07:47 PM    <DIR>          .
05-Nov-14  07:47 PM    <DIR>          ..
22-Jul-14  10:32 AM           213,277 APL+Win EULA - 20140721.pdf
14-Nov-14  07:37 PM         4,357,343 apl.log
18-Aug-14  07:08 PM    <DIR>          APLDraw
18-Aug-14  11:14 AM           226,608 AplFileShExt.dll
18-Aug-14  11:14 AM         1,211,696 APLGrid.dll
10-Jan-14  07:20 AM           877,506 aplgui.chm
19-Dec-11  03:00 PM           602,112 APLIdiomsManager_11111219.msi
12-Aug-14  08:09 PM         2,704,757 APLNext.CSScriptEngineSetup_v1.1.16.exe
12-Aug-14  08:09 PM         3,132,928 APLNext.CSScriptEngineSetup_v1.1.16.msi
16-May-14  11:26 AM            15,664 APLNext.Nfe.dll
09-Nov-11  05:23 PM            97,965 aplni.chm
29-May-14  02:00 PM           416,913 aplplang.chm
18-Aug-14  11:14 AM           297,264 APLUtil.dll
19-May-09  02:35 PM           364,846 aplw.adf
18-Aug-14  11:08 AM         3,824,432 aplw.exe
25-Jul-13  09:09 AM               620 aplw.exe.manifest
18-Aug-14  11:09 AM         3,321,040 aplw.exe.zip
14-Nov-14  05:50 PM             9,764 APLW.INI
29-Sep-14  10:16 PM             9,964 APLW.INI.bak
19-May-09  02:36 PM           348,172 aplwadf.ini
18-Aug-14  11:14 AM           273,712 aplwCo.dll
11-Jul-13  09:21 AM           559,104 APLWinKeyboard_13130711.msi
19-May-09  02:35 PM           364,846 aplwr.adf
18-Aug-14  11:14 AM         2,669,360 aplwr.exe
25-Jul-13  09:09 AM               620 aplwr.exe.manifest
18-Aug-14  11:14 AM           273,712 aplwrCo.dll
11-Aug-14  12:10 PM            13,400 CMDDEMO.SF
18-Jul-14  06:24 AM             3,605 CseHelpStrings.txt
15-Oct-14  06:01 PM    <DIR>          Docs
18-Aug-14  07:08 PM    <DIR>          Examples
18-Aug-14  11:27 AM            22,570 FIXUCMDS.w3
18-Aug-14  07:08 PM    <DIR>          Fonts
09-Jan-14  04:15 PM           445,875 HelpStrings.txt
07-Nov-14  10:50 AM            13,312 LC.CSEObjects.dll
21-Oct-14  04:58 PM             7,138 MYWS_BACKUP.w3
30-Dec-13  02:21 PM             1,424 NfeHelpStrings.txt
15-Aug-14  01:27 PM           149,765 Readme.pdf
09-Aug-96  12:30 AM            30,720 REGSVR32.EXE
30-Mar-98  10:58 AM             1,178 Regsvr32.txt
07-Nov-11  03:02 PM           417,932 sessman.chm
07-Nov-11  03:05 PM            43,763 support.chm
03-Oct-14  08:28 PM    <DIR>          Tools
14-Nov-14  07:15 PM         2,660,560 UCMDS.SF
11-Aug-14  12:11 PM           127,868 UCMDS2.SF
11-Aug-14  12:11 PM           548,100 UCMDS3.SF
11-Aug-14  12:11 PM           447,252 UCMDSW.SF
18-Aug-14  11:14 AM           178,480 unzip32static.dll
15-Aug-14  01:20 PM           164,411 Version_History.pdf
18-Aug-14  11:14 AM           158,000 zip32.dll
              44 File(s)     31,609,578 bytes
               7 Dir(s)  338,412,597,248 bytes free
Eric.Lescasse
 
Posts: 44
Joined: February 8th, 2007, 7:55 pm
Location: Paris, France


Return to APL+Win & The C# Script Engine

Who is online

Users browsing this forum: No registered users and 1 guest