diff options
author | ian.bertolacci <ibertolacci@cray.com> | 2015-07-14 18:40:53 -0700 |
---|---|---|
committer | ian.bertolacci <ibertolacci@cray.com> | 2015-07-14 18:40:53 -0700 |
commit | 2e7ebaa3b940ec9de04f2266138abca58becaf30 (patch) | |
tree | 689cf9e6532812b57daf0f511242de824b000b46 /chapel.html.markdown | |
parent | 343ae6ca1bd908aedfabe1dad948e4efff449628 (diff) |
A number of edits. Some cosmetic. Added iterators, argument/return intents
Diffstat (limited to 'chapel.html.markdown')
-rw-r--r-- | chapel.html.markdown | 129 |
1 files changed, 87 insertions, 42 deletions
diff --git a/chapel.html.markdown b/chapel.html.markdown index 5633214a..ecbab2a2 100644 --- a/chapel.html.markdown +++ b/chapel.html.markdown @@ -28,7 +28,6 @@ writeln( "There are ", 3, " commas (\",\") in this line of code" ); stdout.writeln( "This goes to standard output (just like plain writeln() does)"); stderr.writeln( "This goes to standard error" ); -// Variables // Variables dont have to be explicitly typed as long as // the compiler can figure out the type that it will hold. var myVar = 10; // 10 is an int, so myVar is implicitly an int @@ -123,39 +122,31 @@ writeln( (old_this == thatInt) && (old_that == thisInt) ); // We can also define operator overloads, // which we'll cover with procedures. -// Tuples -// tuples can be of the same type +// Tuples can be of the same type var sameTup: 2*int = (10,-1); +var sameTup2 = (11, -6); // or different types var diffTup: (int,real,complex) = (5, 1.928, myCplx); +var diffTupe2 = ( 7, 5.64, 6.0+1.5i ); // Accessed using array bracket notation // However, tuples are all 1-indexed writeln( "(", sameTup[1], ",", sameTup[2], ")" ); writeln( diffTup ); // Tuples can also be written into. diffTup[1] = -1; -// you can expand tuples as well +// Can expand tuple values into their own variables var (tupInt, tupReal, tupCplx) = diffTup; writeln( diffTup == (tupInt, tupReal, tupCplx) ); -// Can also be used to easily write a collection -// of variables as a list (common in debugging) +// Useful for writing a list of variables ( as is common in debugging) writeln( (a,b,thisInt,thatInt,thisBool,thatBool) ); - // Type aliasing type chroma = int; // type of a single hue type RGBColor = 3*chroma; // type representing a full color var black: RGBColor = ( 0,0,0 ); var white: RGBColor = ( 255, 255, 255 ); - - -// If-Then statements -// if-thens dont require parentheses around the condition -// as they do in C (however, we will use them) -// A single line body can use the 'then' keyword instead of -// braces and else statements can be written similarly - +// if-then-else works just like any other C-family language if 10 < 100 then writeln( "All is well" ); @@ -164,7 +155,6 @@ if -1 < 1 then else writeln( "Send mathematician, something's wrong" ); - if ( 10 > 100 ) { writeln( "Universe broken. Please reboot universe." ); } @@ -219,7 +209,6 @@ do{ }while( j <= 10000 ); writeln( jSum ); - // For loops are much like those in python in that they iterate over a range. // Ranges themselves are types, and can be stuffed into variables // (more about that later) @@ -245,9 +234,11 @@ for x in 1..10 { // Ranges are single dimensional // Domains can be multi-dimensional and can // represent indicies of different types as well. -// They are types, and can be assigned into variables; -var range1to10: range = 1..10; // // 1, 2, 3, ... , 10 +// They are first-class citizen types, and can be assigned into variables +var range1to10: range = 1..10; // 1, 2, 3, ..., 10 var range2to11 = 2..11; // 2, 3, 4, ..., 11 +var rangeThistoThat: range = thisInt..thatInt; // using variables +var rangeEmpty: range = 100..-100 ; // this is a valid, but empty range //ranges can be unbounded var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ... @@ -257,10 +248,12 @@ var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1 // Ranges can be strided using the 'by' operator. var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10 -var reverse2to10by2 = 10..2 by -2; // 10, 8, 6, 4, 2 // Note: the range(stridable=true) is only // necessary if we explicitly type the variable +// Use by to create a reverse range +var reverse2to10by2 = 10..2 by -2; // 10, 8, 6, 4, 2 + // The end point of a range can be determined using the count (#) operator var rangeCount: range = -5..#12; // range from -5 to 6 @@ -278,7 +271,7 @@ for i in rangeCountBy{ write( i, if i == rangeCountBy.last then "\n" else ", " ); } -// Rectangular domains are similarly defined using range notation +// Rectangular domains are defined using the same range syntax var domain1to10: domain(1) = {1..10}; // 1D domain from 1..10; var twoDimensions: domain(2) = {-2..2,0..2}; // 2D domain over product of ranges var thirdDim: range = 1..16; @@ -324,8 +317,7 @@ var realArray2: [1..5,1..7] real; // equivalent var realArray3: [{1..5,1..7}] real; // equivalent for i in 1..5 { - // use the range from 2nd dimension of the domain - for j in realDomain.dim(2) { + 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 var idx: 2*int = (i,j); // note: 'index' is a keyword realArray[idx] = - realArray[(i,j)]; // index using tuples @@ -351,7 +343,7 @@ writeln( rSum, "\n", realArray ); var dictDomain: domain(string) = { "one", "two" }; var dict: [dictDomain] int = [ "one" => 1, "two" => 2 ]; dict["three"] = 3; -writeln( dict ); +for key in dictDomain do writeln( dict[key] ); // Chapel procedures have similar syntax to other languages functions. proc fibonacci( n : int ) : int { @@ -404,7 +396,40 @@ writeln( defaultsProc( x=11 ) ); writeln( defaultsProc( x=12, y=5.432 ) ); writeln( defaultsProc( y=9.876, x=13 ) ); -// We can query the type of arguments to make safer generic procedures +// intent modifiers on the arguments convey how +// those arguments are passed to the procedure +// in: copy arg in, but not out +// out: copy arg out, but not in +// inout: copy arg in, copy arg out +// ref: pass arg by reference +proc intentsProc( in inarg, out outarg, inout inoutarg, ref refarg ){ + writeln( "Inside Before: ", (inarg, outarg, inoutarg, refarg) ); + inarg = inarg + 100; + outarg = outarg + 100; + inoutarg = inoutarg + 100; + refarg = refarg + 100; + writeln( "Inside After: ", (inarg, outarg, inoutarg, refarg) ); +} + +var inVar: int = 1; +var outVar: int = 2; +var inoutVar: int = 3; +var refVar: int = 4; +writeln( "Outside Before: ", (inVar, outVar, inoutVar, refVar) ); +intentsProc( inVar, outVar, inoutVar, refVar ); +writeln( "Outside After: ", (inVar, outVar, inoutVar, refVar) ); + +// Similarly we can define intents on the return type +proc makeArray( elems: int, startNumber: int ) ref : [1..#elems] int { + var array: [1..#elems] int; + for idx in array.domain do array[idx] = startNumber + idx; + return array; +} +writeln( makeArray( 10, -1 ) ); +// this makes more practical sense for class methods where references to +// elements in a data-structure are returned via a method or iterator + +// We can query the type of arguments to generic procedures // Here we define a procedure that takes two arguments of // the same type, yet we dont define what that type is. proc genericProc( arg1 : ?valueType, arg2 : valueType ): void { @@ -421,9 +446,8 @@ genericProc( 1.0+2.0i, 3.0+4.0i ); // We can also enforce a form of polymorphism with the 'where' clause // This allows the compiler to decide which function to use. -// Note: that means that all information needs to be known at compile -// time. Hence, we use params here to assert that the arguments must -// be known at compile time. +// Note: that means that all information needs to be known at compile time. +// The param modifier on the arg is used to enforce this constraint. proc whereProc( param N : int ): void where ( N > 0 ) { writeln( "N is greater than 0" ); @@ -474,6 +498,25 @@ proc +( left: int, right: int ): int{ } */ +// iterators are a close cousin to the procedure. +// However, instead of returning a single value, +// iterators yield many values to a loop. +// 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. +iter oddsThenEvens( N: int ): int { + for i in 1..N by 2 { + yield i; // yield values instead of returning. + } + + for i in 2..N by 2 { + yield i; + } +} + +for i in oddsThenEvens( 10 ) do write( i, ", " ); +writeln(); + + // Classes are similar to those in C++ and Java. // They currently lack privatization class MyClass { @@ -567,16 +610,18 @@ class GenericClass { type classType = otherType ) { this.classDomain = other.classDomain; // Copy and cast - [ idx in this.classDomain ] this[ idx ] = other[ idx ] : classType; + for idx in this.classDomain do this[ idx ] = other[ idx ] : classType; } - // Define bracket notation on a GenericClass object + // Define bracket notation on a GenericClass + // object so it can behave like a normal array // i.e. objVar[ i ] or objVar( i ) proc this( i : int ) ref : classType { return this.classArray[ i ]; } - // Define an iterator for the class. + // Define an iterator for the class to + // yield values from the array to a loop // i.e. for i in objVar do .... iter these() ref : classType { for i in this.classDomain do @@ -604,19 +649,20 @@ var copyNewTypeList = new GenericClass( realList, int ); for value in copyNewTypeList do write( value, ", " ); writeln(); +// Parallelism +// In other languages, parallelism is typically this is done with +// complicated libraries and strange class structure hierarchies. +// Chapel has it baked right into the language. -// A task is some work that will be done separately from the current -// task, and (if there are any available) in its own thread. - +// 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 // main task will not progress until the children have synced back up. sync { -// a begin statement will spin the body off into one new task - begin { + begin { // start of new task's body var a = 0; for i in 1..1000 do a += 1; writeln( "Done: ", a); - } + } // end of new tasks body writeln( "spun off a task!"); } writeln( "Back together" ); @@ -625,12 +671,11 @@ proc printFibb( n: int ){ 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 { - printFibb( 20 ); - printFibb( 10 ); - printFibb( 5 ); + printFibb( 20 ); // new task + printFibb( 10 ); // new task + printFibb( 5 ); // new task { // this is a nested statement body and thus is a single statement // to the parent statement and is executed by a single task |