mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2024-11-26 20:34:32 +03:00
Some rewriting, hopefully the last commit before pull request
This commit is contained in:
parent
2e7ebaa3b9
commit
7640ea4a30
@ -25,29 +25,30 @@ writeln( "World!" );
|
|||||||
// each thing is printed right next to each other, so include your spacing!
|
// each thing is printed right next to each other, so include your spacing!
|
||||||
writeln( "There are ", 3, " commas (\",\") in this line of code" );
|
writeln( "There are ", 3, " commas (\",\") in this line of code" );
|
||||||
// Different output channels
|
// Different output channels
|
||||||
stdout.writeln( "This goes to standard output (just like plain writeln() does)");
|
stdout.writeln( "This goes to standard output (just like plain writeln( ) does)");
|
||||||
stderr.writeln( "This goes to standard error" );
|
stderr.writeln( "This goes to standard error" );
|
||||||
|
|
||||||
// Variables dont have to be explicitly typed as long as
|
// Variables dont have to be explicitly typed as long as
|
||||||
// the compiler can figure out the type that it will hold.
|
// the compiler can figure out the type that it will hold.
|
||||||
var myVar = 10; // 10 is an int, so myVar is implicitly an int
|
var myVar = 10; // 10 is an int, so myVar is implicitly an int
|
||||||
myVar = -10;
|
myVar = -10;
|
||||||
|
var mySecondVar = myVar;
|
||||||
// var anError; // this would be a compile time error.
|
// var anError; // this would be a compile time error.
|
||||||
|
|
||||||
// We can (and should) explicitly type things
|
// We can (and should) explicitly type things
|
||||||
var mySecondVar: real; // define mySecondVar as a real
|
var myThirdVar: real; // define mySecondVar as a real
|
||||||
var myThirdVar: real = -1.234;
|
var myFourthVar: real = -1.234;
|
||||||
mySecondVar = myThirdVar;
|
myThirdVar = myFourthVar;
|
||||||
|
|
||||||
// There are a number of basic types.
|
// There are a number of basic types.
|
||||||
var myInt: int = -1000; // signed ints
|
var myInt: int = -1000; // Signed ints
|
||||||
var myUint: uint = 1234; // unsigned ints
|
var myUint: uint = 1234; // Unsigned ints
|
||||||
var myReal: real = 9.876; // floating point numbers
|
var myReal: real = 9.876; // Floating point numbers
|
||||||
var myImag: imag = 5.0i; // imaginary numbers
|
var myImag: imag = 5.0i; // Imaginary numbers
|
||||||
var myCplx: complex = 10 + 9i; // complex numbers
|
var myCplx: complex = 10 + 9i; // Complex numbers
|
||||||
myCplx = myInt + myImag ; // another way to form complex numbers
|
myCplx = myInt + myImag ; // Another way to form complex numbers
|
||||||
var myBool: bool = false; // booleans
|
var myBool: bool = false; // Booleans
|
||||||
var myStr: string = "Some string..."; // strings
|
var myStr: string = "Some string..."; // Strings
|
||||||
|
|
||||||
// Some types can have sizes
|
// Some types can have sizes
|
||||||
var my8Int: int(8) = 10; // 8 bit (one byte) sized int;
|
var my8Int: int(8) = 10; // 8 bit (one byte) sized int;
|
||||||
@ -59,6 +60,7 @@ var intFromReal2: int = myReal : int;
|
|||||||
|
|
||||||
// consts are constants, they cannot be changed after set in runtime
|
// consts are constants, they cannot be changed after set in runtime
|
||||||
const almostPi: real = 22.0/7.0;
|
const almostPi: real = 22.0/7.0;
|
||||||
|
|
||||||
// params are constants whose value must be known statically at compile time
|
// params are constants whose value must be known statically at compile time
|
||||||
// Like consts, they cannot be changed during runtime
|
// Like consts, they cannot be changed during runtime
|
||||||
param compileTimeConst: int = 16;
|
param compileTimeConst: int = 16;
|
||||||
@ -68,47 +70,47 @@ param compileTimeConst: int = 16;
|
|||||||
// config vars and consts can be changed through the command line at run time
|
// config vars and consts can be changed through the command line at run time
|
||||||
config var varCmdLineArg: int = -123;
|
config var varCmdLineArg: int = -123;
|
||||||
config const constCmdLineArg: int = 777;
|
config const constCmdLineArg: int = 777;
|
||||||
// set with --VarName=Value or --VarName Value at run time
|
// Set with --VarName=Value or --VarName Value at run time
|
||||||
|
|
||||||
// config params can be set at compile time
|
// config params can be set at compile time
|
||||||
config param paramCmdLineArg: bool = false;
|
config param paramCmdLineArg: bool = false;
|
||||||
writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg );
|
writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg );
|
||||||
//set config with --set paramCmdLineArg=value at compile time
|
// Set config with --set paramCmdLineArg=value at compile time
|
||||||
|
|
||||||
// Math operators
|
// Math operators
|
||||||
var a: int, thisInt = 1234, thatInt = 5678;
|
var a: int, thisInt = 1234, thatInt = 5678;
|
||||||
a = thisInt + thatInt; // Addition
|
a = thisInt + thatInt; // Addition
|
||||||
a = thisInt * thatInt; // Multiplication
|
a = thisInt * thatInt; // Multiplication
|
||||||
a = thisInt - thatInt; // Subtraction
|
a = thisInt - thatInt; // Subtraction
|
||||||
a = thisInt / thatInt; // division
|
a = thisInt / thatInt; // Division
|
||||||
a = thisInt ** thatInt; // exponentiation
|
a = thisInt ** thatInt; // Exponentiation
|
||||||
a = thisInt % thatInt; // remainder (modulo)
|
a = thisInt % thatInt; // Remainder (modulo)
|
||||||
|
|
||||||
// Logical Operators
|
// Logical Operators
|
||||||
var b: bool, thisBool = false, thatBool = true;
|
var b: bool, thisBool = false, thatBool = true;
|
||||||
b = thisBool && thatBool; // logical and
|
b = thisBool && thatBool; // Logical and
|
||||||
b = thisBool || thatBool; // logical or
|
b = thisBool || thatBool; // Logical or
|
||||||
b = !thisBool; // logical negation
|
b = !thisBool; // Logical negation
|
||||||
|
|
||||||
// Relational Operators
|
// Relational Operators
|
||||||
b = thisInt > thatInt; // greater-than
|
b = thisInt > thatInt; // Greater-than
|
||||||
b = thisInt >= thatInt; // greater-than-or-equal-to
|
b = thisInt >= thatInt; // Greater-than-or-equal-to
|
||||||
b = thisInt < a && a <= thatInt; // less-than, and, less-than-or-equal-to
|
b = thisInt < a && a <= thatInt; // Less-than, and, less-than-or-equal-to
|
||||||
b = thisInt != thatInt; // not-equal-to
|
b = thisInt != thatInt; // Not-equal-to
|
||||||
b = thisInt == thatInt; // equal-to
|
b = thisInt == thatInt; // Equal-to
|
||||||
|
|
||||||
// Bitwise operations
|
// Bitwise operations
|
||||||
a = thisInt << 10; // left-bit-shift by 10 bits;
|
a = thisInt << 10; // Left-bit-shift by 10 bits;
|
||||||
a = thatInt >> 5; // right-bit-shift by 5 bits;
|
a = thatInt >> 5; // Right-bit-shift by 5 bits;
|
||||||
a = ~thisInt; // bitwise-negation
|
a = ~thisInt; // Bitwise-negation
|
||||||
a = thisInt ^ thatInt; // bitwise exclusive-or
|
a = thisInt ^ thatInt; // Bitwise exclusive-or
|
||||||
|
|
||||||
// Compound assignment operations
|
// Compound assignment operations
|
||||||
a += thisInt; // addition-equals ( a = a + thisInt;)
|
a += thisInt; // Addition-equals ( a = a + thisInt;)
|
||||||
a *= thatInt; // times-equals ( a = a * thatInt; )
|
a *= thatInt; // Times-equals ( a = a * thatInt; )
|
||||||
b &&= thatBool; // logical-and-equals ( b = b && thatBool; )
|
b &&= thatBool; // Logical-and-equals ( b = b && thatBool; )
|
||||||
a <<= 3; // left-bit-shift-equals ( a = a << 10; )
|
a <<= 3; // LEft-bit-shift-equals ( a = a << 10; )
|
||||||
// and so on...
|
// and many, many more.
|
||||||
// Unlike other C family languages there are no
|
// Unlike other C family languages there are no
|
||||||
// pre/post-increment/decrement operators like
|
// pre/post-increment/decrement operators like
|
||||||
// ++j, --j, j++, j--
|
// ++j, --j, j++, j--
|
||||||
@ -119,8 +121,7 @@ var old_that = thatInt;
|
|||||||
thisInt <=> thatInt; // Swap the values of thisInt and thatInt
|
thisInt <=> thatInt; // Swap the values of thisInt and thatInt
|
||||||
writeln( (old_this == thatInt) && (old_that == thisInt) );
|
writeln( (old_this == thatInt) && (old_that == thisInt) );
|
||||||
|
|
||||||
// We can also define operator overloads,
|
// Operator overloads can also be defined, as we'll see with procedures
|
||||||
// which we'll cover with procedures.
|
|
||||||
|
|
||||||
// Tuples can be of the same type
|
// Tuples can be of the same type
|
||||||
var sameTup: 2*int = (10,-1);
|
var sameTup: 2*int = (10,-1);
|
||||||
@ -128,25 +129,29 @@ var sameTup2 = (11, -6);
|
|||||||
// or different types
|
// or different types
|
||||||
var diffTup: (int,real,complex) = (5, 1.928, myCplx);
|
var diffTup: (int,real,complex) = (5, 1.928, myCplx);
|
||||||
var diffTupe2 = ( 7, 5.64, 6.0+1.5i );
|
var diffTupe2 = ( 7, 5.64, 6.0+1.5i );
|
||||||
|
|
||||||
// Accessed using array bracket notation
|
// Accessed using array bracket notation
|
||||||
// However, tuples are all 1-indexed
|
// However, tuples are all 1-indexed
|
||||||
writeln( "(", sameTup[1], ",", sameTup[2], ")" );
|
writeln( "(", sameTup[1], ",", sameTup[2], ")" );
|
||||||
writeln( diffTup );
|
writeln( diffTup );
|
||||||
|
|
||||||
// Tuples can also be written into.
|
// Tuples can also be written into.
|
||||||
diffTup[1] = -1;
|
diffTup[1] = -1;
|
||||||
|
|
||||||
// Can expand tuple values into their own variables
|
// Can expand tuple values into their own variables
|
||||||
var (tupInt, tupReal, tupCplx) = diffTup;
|
var (tupInt, tupReal, tupCplx) = diffTup;
|
||||||
writeln( diffTup == (tupInt, tupReal, tupCplx) );
|
writeln( diffTup == (tupInt, tupReal, tupCplx) );
|
||||||
|
|
||||||
// Useful for writing a list of variables ( as is common in debugging)
|
// Useful for writing a list of variables ( as is common in debugging)
|
||||||
writeln( (a,b,thisInt,thatInt,thisBool,thatBool) );
|
writeln( (a,b,thisInt,thatInt,thisBool,thatBool) );
|
||||||
|
|
||||||
// Type aliasing
|
// Type aliasing
|
||||||
type chroma = int; // type of a single hue
|
type chroma = int; // Type of a single hue
|
||||||
type RGBColor = 3*chroma; // type representing a full color
|
type RGBColor = 3*chroma; // Type representing a full color
|
||||||
var black: RGBColor = ( 0,0,0 );
|
var black: RGBColor = ( 0,0,0 );
|
||||||
var white: RGBColor = ( 255, 255, 255 );
|
var white: RGBColor = ( 255, 255, 255 );
|
||||||
|
|
||||||
// if-then-else works just like any other C-family language
|
// If-then-else works just like any other C-family language
|
||||||
if 10 < 100 then
|
if 10 < 100 then
|
||||||
writeln( "All is well" );
|
writeln( "All is well" );
|
||||||
|
|
||||||
@ -193,16 +198,16 @@ select( inputOption ){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// While loops and Do-While loops are basically the same in every language.
|
// While and Do-While loops are basically the same in every language.
|
||||||
var j: int = 1;
|
var j: int = 1;
|
||||||
var jSum: int = 0;
|
var jSum: int = 0;
|
||||||
while( j <= 1000 ){
|
while( j <= 1000 ){
|
||||||
jSum += j;
|
jSum += j;
|
||||||
j += 1; // there are no ++j, --j, j++, j--, operators
|
j += 1;
|
||||||
}
|
}
|
||||||
writeln( jSum );
|
writeln( jSum );
|
||||||
|
|
||||||
// basic Do-While loop
|
// Do-While loop
|
||||||
do{
|
do{
|
||||||
jSum += j;
|
jSum += j;
|
||||||
j += 1;
|
j += 1;
|
||||||
@ -213,7 +218,7 @@ writeln( jSum );
|
|||||||
// Ranges themselves are types, and can be stuffed into variables
|
// Ranges themselves are types, and can be stuffed into variables
|
||||||
// (more about that later)
|
// (more about that later)
|
||||||
for i in 1..10 do write( i , ", ") ;
|
for i in 1..10 do write( i , ", ") ;
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
var iSum: int = 0;
|
var iSum: int = 0;
|
||||||
for i in 1..1000 {
|
for i in 1..1000 {
|
||||||
@ -225,7 +230,7 @@ for x in 1..10 {
|
|||||||
for y in 1..10 {
|
for y in 1..10 {
|
||||||
write( (x,y), "\t" );
|
write( (x,y), "\t" );
|
||||||
}
|
}
|
||||||
writeln();
|
writeln( );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ranges and Domains
|
// Ranges and Domains
|
||||||
@ -238,14 +243,16 @@ for x in 1..10 {
|
|||||||
var range1to10: range = 1..10; // 1, 2, 3, ..., 10
|
var range1to10: range = 1..10; // 1, 2, 3, ..., 10
|
||||||
var range2to11 = 2..11; // 2, 3, 4, ..., 11
|
var range2to11 = 2..11; // 2, 3, 4, ..., 11
|
||||||
var rangeThistoThat: range = thisInt..thatInt; // using variables
|
var rangeThistoThat: range = thisInt..thatInt; // using variables
|
||||||
var rangeEmpty: range = 100..-100 ; // this is a valid, but empty range
|
var rangeEmpty: range = 100..-100 ; // this is valid but contains no indices
|
||||||
|
|
||||||
//ranges can be unbounded
|
// Ranges can be unbounded
|
||||||
var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ...
|
var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ;
|
||||||
var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
|
// 1, 2, 3, 4, 5, ...
|
||||||
// Note: the range(boundedType= ... ) is only
|
// Note: the range(boundedType= ... ) is only
|
||||||
// necessary if we explicitly type the variable
|
// necessary if we explicitly type the variable
|
||||||
|
|
||||||
|
var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
|
||||||
|
|
||||||
// Ranges can be strided using the 'by' operator.
|
// Ranges can be strided using the 'by' operator.
|
||||||
var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
|
var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
|
||||||
// Note: the range(stridable=true) is only
|
// Note: the range(stridable=true) is only
|
||||||
@ -280,24 +287,23 @@ var threeDims: domain(3) = {thirdDim, 1..10, 5..10}; // using a range variable
|
|||||||
// Can iterate over the indices as tuples
|
// Can iterate over the indices as tuples
|
||||||
for idx in twoDimensions do
|
for idx in twoDimensions do
|
||||||
write( idx , ", ");
|
write( idx , ", ");
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
// Or can deconstruct the tuple
|
// or can deconstruct the tuple
|
||||||
for (x,y) in twoDimensions {
|
for (x,y) in twoDimensions {
|
||||||
write( "(", x, ", ", y, ")", ", " );
|
write( "(", x, ", ", y, ")", ", " );
|
||||||
}
|
}
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
// Associative domains act like sets
|
// Associative domains act like sets
|
||||||
var stringSet: domain(string); // empty set of strings
|
var stringSet: domain(string); // empty set of strings
|
||||||
stringSet += "a";
|
stringSet += "a";
|
||||||
stringSet += "b";
|
stringSet += "b";
|
||||||
stringSet += "c";
|
stringSet += "c";
|
||||||
stringSet += "a"; // redundant add "a"
|
stringSet += "a"; // Redundant add "a"
|
||||||
stringSet -= "c"; // remove "c"
|
stringSet -= "c"; // Remove "c"
|
||||||
writeln( stringSet );
|
writeln( stringSet );
|
||||||
|
|
||||||
|
|
||||||
// Array are similar to those of other languages.
|
// Array are similar to those of other languages.
|
||||||
// Their sizes are defined using domains that represent their indices
|
// Their sizes are defined using domains that represent their indices
|
||||||
var intArray: [1..10] int;
|
var intArray: [1..10] int;
|
||||||
@ -307,35 +313,35 @@ var intArray2: [{1..10}] int; //equivalent
|
|||||||
for i in 1..10 do
|
for i in 1..10 do
|
||||||
intArray[i] = -i;
|
intArray[i] = -i;
|
||||||
writeln( intArray );
|
writeln( intArray );
|
||||||
// we cannot access intArray[0] because it exists outside
|
// We cannot access intArray[0] because it exists outside
|
||||||
// of the index set, {1..10}, we defined it to have
|
// of the index set, {1..10}, we defined it to have.
|
||||||
// intArray[11] is illegal for the same reason.
|
// intArray[11] is illegal for the same reason.
|
||||||
|
|
||||||
var realDomain: domain(2) = {1..5,1..7};
|
var realDomain: domain(2) = {1..5,1..7};
|
||||||
var realArray: [realDomain] real;
|
var realArray: [realDomain] real;
|
||||||
var realArray2: [1..5,1..7] real; // equivalent
|
var realArray2: [1..5,1..7] real; // Equivalent
|
||||||
var realArray3: [{1..5,1..7}] real; // equivalent
|
var realArray3: [{1..5,1..7}] real; // Equivalent
|
||||||
|
|
||||||
for i in 1..5 {
|
for i in 1..5 {
|
||||||
for j in realDomain.dim(2) { // only use the 2nd dimension of the domain
|
for j in realDomain.dim(2) { // Only use the 2nd dimension of the domain
|
||||||
realArray[i,j] = -1.61803 * i + 0.5 * j; // access using index list
|
realArray[i,j] = -1.61803 * i + 0.5 * j; // Access using index list
|
||||||
var idx: 2*int = (i,j); // note: 'index' is a keyword
|
var idx: 2*int = (i,j); // Note: 'index' is a keyword
|
||||||
realArray[idx] = - realArray[(i,j)]; // index using tuples
|
realArray[idx] = - realArray[(i,j)]; // Index using tuples
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// arrays have domains as members that we can iterate over
|
// Arrays have domains as members that we can iterate over
|
||||||
for idx in realArray.domain { // again, idx is a 2*int tuple
|
for idx in realArray.domain { // Again, idx is a 2*int tuple
|
||||||
realArray[idx] = 1 / realArray[idx[1],idx[2]]; // access by tuple and list
|
realArray[idx] = 1 / realArray[idx[1],idx[2]]; // Access by tuple and list
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln( realArray );
|
writeln( realArray );
|
||||||
|
|
||||||
// can also iterate over the values of an array
|
// Can also iterate over the values of an array
|
||||||
var rSum: real = 0;
|
var rSum: real = 0;
|
||||||
for value in realArray {
|
for value in realArray {
|
||||||
rSum += value; // read a value
|
rSum += value; // Read a value
|
||||||
value = rSum; // write a value
|
value = rSum; // Write a value
|
||||||
}
|
}
|
||||||
writeln( rSum, "\n", realArray );
|
writeln( rSum, "\n", realArray );
|
||||||
|
|
||||||
@ -351,12 +357,12 @@ proc fibonacci( n : int ) : int {
|
|||||||
return fibonacci( n-1 ) + fibonacci( n-2 );
|
return fibonacci( n-1 ) + fibonacci( n-2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// input parameters can be untyped (a generic procedure)
|
// Input parameters can be untyped (a generic procedure)
|
||||||
proc doublePrint( thing ): void {
|
proc doublePrint( thing ): void {
|
||||||
write( thing, " ", thing, "\n");
|
write( thing, " ", thing, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
// return type can be inferred (as long as the compiler can figure it out)
|
// Return type can be inferred (as long as the compiler can figure it out)
|
||||||
proc addThree( n ) {
|
proc addThree( n ) {
|
||||||
return n + 3;
|
return n + 3;
|
||||||
}
|
}
|
||||||
@ -372,12 +378,12 @@ proc maxOf( x ...?k ) {
|
|||||||
}
|
}
|
||||||
writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) );
|
writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) );
|
||||||
|
|
||||||
// the ? operator is called the query operator, and is used to take
|
// The ? operator is called the query operator, and is used to take
|
||||||
// undetermined values (like tuple or array sizes, and generic types).
|
// undetermined values (like tuple or array sizes, and generic types).
|
||||||
|
|
||||||
// Taking arrays as parameters.
|
// Taking arrays as parameters.
|
||||||
// The query operator is used to determine the domain of A.
|
// The query operator is used to determine the domain of A.
|
||||||
// this is important to define the return type (if you wanted to)
|
// This is important to define the return type (if you wanted to)
|
||||||
proc invertArray( A: [?D] int ): [D] int{
|
proc invertArray( A: [?D] int ): [D] int{
|
||||||
for a in A do a = -a;
|
for a in A do a = -a;
|
||||||
return A;
|
return A;
|
||||||
@ -396,7 +402,7 @@ writeln( defaultsProc( x=11 ) );
|
|||||||
writeln( defaultsProc( x=12, y=5.432 ) );
|
writeln( defaultsProc( x=12, y=5.432 ) );
|
||||||
writeln( defaultsProc( y=9.876, x=13 ) );
|
writeln( defaultsProc( y=9.876, x=13 ) );
|
||||||
|
|
||||||
// intent modifiers on the arguments convey how
|
// Intent modifiers on the arguments convey how
|
||||||
// those arguments are passed to the procedure
|
// those arguments are passed to the procedure
|
||||||
// in: copy arg in, but not out
|
// in: copy arg in, but not out
|
||||||
// out: copy arg out, but not in
|
// out: copy arg out, but not in
|
||||||
@ -426,7 +432,7 @@ proc makeArray( elems: int, startNumber: int ) ref : [1..#elems] int {
|
|||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
writeln( makeArray( 10, -1 ) );
|
writeln( makeArray( 10, -1 ) );
|
||||||
// this makes more practical sense for class methods where references to
|
// This makes more practical sense for class methods where references to
|
||||||
// elements in a data-structure are returned via a method or iterator
|
// elements in a data-structure are returned via a method or iterator
|
||||||
|
|
||||||
// We can query the type of arguments to generic procedures
|
// We can query the type of arguments to generic procedures
|
||||||
@ -462,17 +468,17 @@ whereProc( 10 );
|
|||||||
whereProc( -1 );
|
whereProc( -1 );
|
||||||
// whereProc( 0 ) would result in a compiler error because there
|
// whereProc( 0 ) would result in a compiler error because there
|
||||||
// are no functions that satisfy the where clause's condition.
|
// are no functions that satisfy the where clause's condition.
|
||||||
// We could have defined a whereProc without a where clause that would
|
// We could have defined a whereProc without a where clause that would then have
|
||||||
// then have been called.
|
// served as a catch all for all the other cases (of which there is only one).
|
||||||
|
|
||||||
// Operator definitions are through procedures as well
|
// Operator definitions are through procedures as well.
|
||||||
// we can define the unary operators:
|
// We can define the unary operators:
|
||||||
// + - ! ~
|
// + - ! ~
|
||||||
// and the binary operators:
|
// and the binary operators:
|
||||||
// + - * / % ** == <= >= < > << >> & | ˆ by
|
// + - * / % ** == <= >= < > << >> & | ˆ by
|
||||||
// += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
|
// += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
|
||||||
|
|
||||||
// boolean exclusive or operator
|
// Boolean exclusive or operator
|
||||||
proc ^( left : bool, right : bool ): bool {
|
proc ^( left : bool, right : bool ): bool {
|
||||||
return (left || right) && !( left && right );
|
return (left || right) && !( left && right );
|
||||||
}
|
}
|
||||||
@ -487,8 +493,8 @@ proc *( left : ?ltype, right : ?rtype): ( ltype, rtype ){
|
|||||||
return (left, right );
|
return (left, right );
|
||||||
}
|
}
|
||||||
|
|
||||||
writeln( 1 * "a" ); // uses our * operator
|
writeln( 1 * "a" ); // Uses our * operator
|
||||||
writeln( 1 * 2 ); // uses the original * operator
|
writeln( 1 * 2 ); // Uses the default * operator
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Note: You could break everything if you get careless with your overloads.
|
Note: You could break everything if you get careless with your overloads.
|
||||||
@ -498,24 +504,21 @@ proc +( left: int, right: int ): int{
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// iterators are a close cousin to the procedure.
|
// Iterators are a sisters to the procedure, and almost
|
||||||
|
// everything about procedures also applies to iterators
|
||||||
// However, instead of returning a single value,
|
// However, instead of returning a single value,
|
||||||
// iterators yield many values to a loop.
|
// iterators yield many values to a loop.
|
||||||
// This is useful when a complicated set or order of iterations is needed but
|
// This is useful when a complicated set or order of iterations is needed but
|
||||||
// allows the code defining the iterations to be separate from the loop body.
|
// allows the code defining the iterations to be separate from the loop body.
|
||||||
iter oddsThenEvens( N: int ): int {
|
iter oddsThenEvens( N: int ): int {
|
||||||
for i in 1..N by 2 {
|
for i in 1..N by 2 do
|
||||||
yield i; // yield values instead of returning.
|
yield i; // yield values instead of returning.
|
||||||
}
|
for i in 2..N by 2 do
|
||||||
|
|
||||||
for i in 2..N by 2 {
|
|
||||||
yield i;
|
yield i;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in oddsThenEvens( 10 ) do write( i, ", " );
|
for i in oddsThenEvens( 10 ) do write( i, ", " );
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
|
|
||||||
// Classes are similar to those in C++ and Java.
|
// Classes are similar to those in C++ and Java.
|
||||||
// They currently lack privatization
|
// They currently lack privatization
|
||||||
@ -548,7 +551,7 @@ class MyClass {
|
|||||||
return this.memberInt;
|
return this.memberInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
proc getMemberBool(): bool {
|
proc getMemberBool( ): bool {
|
||||||
return this.memberBool;
|
return this.memberBool;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,30 +559,30 @@ class MyClass {
|
|||||||
|
|
||||||
// Construct using default constructor, using default values
|
// Construct using default constructor, using default values
|
||||||
var myObject = new MyClass( 10 );
|
var myObject = new MyClass( 10 );
|
||||||
myObject = new MyClass( memberInt = 10 ); // equivalent
|
myObject = new MyClass( memberInt = 10 ); // Equivalent
|
||||||
writeln( myObject.getMemberInt() );
|
writeln( myObject.getMemberInt( ) );
|
||||||
// ... using our values
|
// ... using our values
|
||||||
var myDiffObject = new MyClass( -1, true );
|
var myDiffObject = new MyClass( -1, true );
|
||||||
myDiffObject = new MyClass( memberInt = -1,
|
myDiffObject = new MyClass( memberInt = -1,
|
||||||
memberBool = true ); // equivalent
|
memberBool = true ); // Equivalent
|
||||||
writeln( myDiffObject );
|
writeln( myDiffObject );
|
||||||
|
|
||||||
// Construct using written constructor
|
// Construct using written constructor
|
||||||
var myOtherObject = new MyClass( 1.95 );
|
var myOtherObject = new MyClass( 1.95 );
|
||||||
myOtherObject = new MyClass( val = 1.95 ); // equivalent
|
myOtherObject = new MyClass( val = 1.95 ); // Equivalent
|
||||||
writeln( myOtherObject.getMemberInt() );
|
writeln( myOtherObject.getMemberInt( ) );
|
||||||
|
|
||||||
// We can define an operator on our class as well but
|
// We can define an operator on our class as well but
|
||||||
// the definition has to be outside the class definition
|
// the definition has to be outside the class definition
|
||||||
proc +( A : MyClass, B : MyClass) : MyClass {
|
proc +( A : MyClass, B : MyClass) : MyClass {
|
||||||
return new MyClass( memberInt = A.getMemberInt() + B.getMemberInt(),
|
return new MyClass( memberInt = A.getMemberInt( ) + B.getMemberInt( ),
|
||||||
memberBool = A.getMemberBool() || B.getMemberBool() );
|
memberBool = A.getMemberBool( ) || B.getMemberBool( ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
var plusObject = myObject + myDiffObject;
|
var plusObject = myObject + myDiffObject;
|
||||||
writeln( plusObject );
|
writeln( plusObject );
|
||||||
|
|
||||||
// destruction
|
// Destruction
|
||||||
delete myObject;
|
delete myObject;
|
||||||
delete myDiffObject;
|
delete myDiffObject;
|
||||||
delete myOtherObject;
|
delete myOtherObject;
|
||||||
@ -620,10 +623,10 @@ class GenericClass {
|
|||||||
return this.classArray[ i ];
|
return this.classArray[ i ];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define an iterator for the class to
|
// Define an implicit iterator for the class
|
||||||
// yield values from the array to a loop
|
// to yield values from the array to a loop
|
||||||
// i.e. for i in objVar do ....
|
// i.e. for i in objVar do ....
|
||||||
iter these() ref : classType {
|
iter these( ) ref : classType {
|
||||||
for i in this.classDomain do
|
for i in this.classDomain do
|
||||||
yield this[i];
|
yield this[i];
|
||||||
}
|
}
|
||||||
@ -635,19 +638,19 @@ var realList = new GenericClass( real, 10 );
|
|||||||
// notation that we defined ( proc this( i: int ){ ... } )
|
// notation that we defined ( proc this( i: int ){ ... } )
|
||||||
for i in realList.classDomain do realList[i] = i + 1.0;
|
for i in realList.classDomain do realList[i] = i + 1.0;
|
||||||
// We can iterate over the values in our list with the iterator
|
// We can iterate over the values in our list with the iterator
|
||||||
// we defined ( iter these(){ ... } )
|
// we defined ( iter these( ){ ... } )
|
||||||
for value in realList do write( value, ", " );
|
for value in realList do write( value, ", " );
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
// Make a copy of realList using the copy constructor
|
// Make a copy of realList using the copy constructor
|
||||||
var copyList = new GenericClass( realList );
|
var copyList = new GenericClass( realList );
|
||||||
for value in copyList do write( value, ", " );
|
for value in copyList do write( value, ", " );
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
// make a copy of realList and change the type, also using the copy constructor
|
// Make a copy of realList and change the type, also using the copy constructor
|
||||||
var copyNewTypeList = new GenericClass( realList, int );
|
var copyNewTypeList = new GenericClass( realList, int );
|
||||||
for value in copyNewTypeList do write( value, ", " );
|
for value in copyNewTypeList do write( value, ", " );
|
||||||
writeln();
|
writeln( );
|
||||||
|
|
||||||
// Parallelism
|
// Parallelism
|
||||||
// In other languages, parallelism is typically this is done with
|
// In other languages, parallelism is typically this is done with
|
||||||
@ -655,14 +658,14 @@ writeln();
|
|||||||
// Chapel has it baked right into the language.
|
// Chapel has it baked right into the language.
|
||||||
|
|
||||||
// A begin statement will spin the body of that statement off into one new task.
|
// A begin statement will spin the body of that statement off into one new task.
|
||||||
// a sync statement will ensure that the progress of the
|
// A sync statement will ensure that the progress of the main
|
||||||
// main task will not progress until the children have synced back up.
|
// task will not progress until the children have synced back up.
|
||||||
sync {
|
sync {
|
||||||
begin { // start of new task's body
|
begin { // Start of new task's body
|
||||||
var a = 0;
|
var a = 0;
|
||||||
for i in 1..1000 do a += 1;
|
for i in 1..1000 do a += 1;
|
||||||
writeln( "Done: ", a);
|
writeln( "Done: ", a);
|
||||||
} // end of new tasks body
|
} // End of new tasks body
|
||||||
writeln( "spun off a task!");
|
writeln( "spun off a task!");
|
||||||
}
|
}
|
||||||
writeln( "Back together" );
|
writeln( "Back together" );
|
||||||
@ -671,13 +674,13 @@ proc printFibb( n: int ){
|
|||||||
writeln( "fibonacci(",n,") = ", fibonacci( n ) );
|
writeln( "fibonacci(",n,") = ", fibonacci( n ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// a cobegin statement will spin each statement of the body into one new task
|
// A cobegin statement will spin each statement of the body into one new task
|
||||||
cobegin {
|
cobegin {
|
||||||
printFibb( 20 ); // new task
|
printFibb( 20 ); // new task
|
||||||
printFibb( 10 ); // new task
|
printFibb( 10 ); // new task
|
||||||
printFibb( 5 ); // new task
|
printFibb( 5 ); // new task
|
||||||
{
|
{
|
||||||
// this is a nested statement body and thus is a single statement
|
// This is a nested statement body and thus is a single statement
|
||||||
// to the parent statement and is executed by a single task
|
// to the parent statement and is executed by a single task
|
||||||
writeln( "this gets" );
|
writeln( "this gets" );
|
||||||
writeln( "executed as" );
|
writeln( "executed as" );
|
||||||
@ -700,41 +703,41 @@ coforall taskID in 1..#num_tasks {
|
|||||||
forall i in 1..100 {
|
forall i in 1..100 {
|
||||||
write( i, ", ");
|
write( i, ", ");
|
||||||
}
|
}
|
||||||
writeln();
|
writeln( );
|
||||||
// Here we see that there are sections that are in order, followed by
|
// Here we see that there are sections that are in order, followed by
|
||||||
// a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, )
|
// a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, ).
|
||||||
// this is because each task is taking on a chunk of the range 1..10
|
// This is because each task is taking on a chunk of the range 1..10
|
||||||
// (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
|
// (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
|
||||||
// in parallel.
|
// in parallel.
|
||||||
// Your results may depend on your machine and configuration
|
// Your results may depend on your machine and configuration
|
||||||
|
|
||||||
// For both the forall and coforall loops, the execution of the parent task
|
// For both the forall and coforall loops, the execution of the
|
||||||
// will not continue until all the children sync up.
|
// parent task will not continue until all the children sync up.
|
||||||
|
|
||||||
// forall loops are particularly useful for parallel iteration over arrays
|
// forall loops are particularly useful for parallel iteration over arrays.
|
||||||
// Lets run an experiment to see how much faster a parallel loop is
|
// Lets run an experiment to see how much faster a parallel loop is
|
||||||
use Time; // Import the Time module to use Timer objects
|
use Time; // Import the Time module to use Timer objects
|
||||||
var timer: Timer;
|
var timer: Timer;
|
||||||
var myBigArray: [{1..4000,1..4000}] real; // large array we will write into
|
var myBigArray: [{1..4000,1..4000}] real; // Large array we will write into
|
||||||
// Serial Experiment
|
// Serial Experiment
|
||||||
timer.start(); // start timer
|
timer.start( ); // Start timer
|
||||||
for (x,y) in myBigArray.domain { // serial iteration
|
for (x,y) in myBigArray.domain { // Serial iteration
|
||||||
myBigArray[x,y] = (x:real) / (y:real);
|
myBigArray[x,y] = (x:real) / (y:real);
|
||||||
}
|
}
|
||||||
timer.stop(); // stop timer
|
timer.stop( ); // Stop timer
|
||||||
writeln( "Serial: ", timer.elapsed() ); // print elapsed time
|
writeln( "Serial: ", timer.elapsed( ) ); // Print elapsed time
|
||||||
timer.clear(); // clear timer for parallel loop
|
timer.clear( ); // Clear timer for parallel loop
|
||||||
|
|
||||||
// Parallel Experiment
|
// Parallel Experiment
|
||||||
timer.start(); // start timer
|
timer.start( ); // start timer
|
||||||
forall (x,y) in myBigArray.domain { // parallel iteration
|
forall (x,y) in myBigArray.domain { // Parallel iteration
|
||||||
myBigArray[x,y] = (x:real) / (y:real);
|
myBigArray[x,y] = (x:real) / (y:real);
|
||||||
}
|
}
|
||||||
timer.stop(); // stop timer
|
timer.stop( ); // Stop timer
|
||||||
writeln( "Parallel: ", timer.elapsed() ); // print elapsed time
|
writeln( "Parallel: ", timer.elapsed( ) ); // Print elapsed time
|
||||||
timer.clear();
|
timer.clear( );
|
||||||
// you may have noticed that (depending on how many cores you have) that
|
// You may have noticed that (depending on how many cores you have)
|
||||||
// the parallel loop went faster than the serial loop
|
// that the parallel loop went faster than the serial loop
|
||||||
|
|
||||||
// A succinct way of writing a forall loop over an array:
|
// A succinct way of writing a forall loop over an array:
|
||||||
// iterate over values
|
// iterate over values
|
||||||
@ -750,6 +753,17 @@ Refer to the [language specification](http://chapel.cray.com/language.html) and
|
|||||||
|
|
||||||
Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created.
|
Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created.
|
||||||
|
|
||||||
|
### What this tutorial is lacking:
|
||||||
|
* Modules and standard modules
|
||||||
|
* Synchronize and atomic variables
|
||||||
|
* Multiple Locales (distributed memory system)
|
||||||
|
* proc main(){ ... }
|
||||||
|
* Records
|
||||||
|
* Whole/sliced array assignment
|
||||||
|
* Reductions and scans
|
||||||
|
* Range and domain slicing
|
||||||
|
* Parallel iterators
|
||||||
|
|
||||||
Your input, questions, and discoveries are important to the developers!
|
Your input, questions, and discoveries are important to the developers!
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features.
|
The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features.
|
||||||
|
Loading…
Reference in New Issue
Block a user