JS Subset in WebPPL
JS Subset in WebPPL
Nonstochastic JS Test Cases in WebPPL
The text of this WebPPL-script file can be copied and run in the WebPPL-box which can be found here: webppl.org.
console.log("==============================================================================")
console.log("file: 'PCM20180310_JS_in_WebPPL' by PCM *** version 2018/03/21 ***")
console.log(" This file contains JS test cases executable in WebPPL ")
console.log(" *** beware, array methods are not referential transparent ! **** ")
console.log("WebPPL is a pure functional DSL (= Domain Specific language) embedded in JS")
console.log("examples are similar but not identical to those in 'Core JavaScript',")
console.log(" ch.1.1 in David Flanagan 'JavaScript: The Definitive Guide', 2011. 6/e")
console.log("==============================================================================")
console.log("'console.log(...)' generates output in the browser's web console")
console.log("comment: anything following double slashes '//' is a comment")
console.log("")
console.log("the test template has this structure:")
console.log(" <stringOfTestDescription> '--->' <expression> <compOperator> <targetValue>")
console.log("")
console.log("<stringOfTestDescription>, ... an informal description of the test ")
console.log("'--->', symbol with meaning '<expression> (left) evaluates to <value> (right)'")
console.log("<expression>, ... a WebPPL-expression")
console.log("<compOperator>, ... a comparison operator ==, !=, ===, !==, <, >, ... ")
console.log("<compOperator> '==' means a 'test of equality' (beware of type coercion !)")
console.log("<compOperator> '===' means a 'test of strict equality'")
console.log("<targetValue>, ... an expected value; should not deviate from <value> !")
console.log("")
console.log(" ***important *** all tests should evaluate to ***true***")
console.log("==============================================================================")
console.log("variable: a variable is a symbolic name for a value")
console.log("var pi = 3.141") // declare a variable named 'pi' with value '3.141'
var pi = 3.141
console.log("pi === 3.141 --->", pi === 3.141) // should be 'true'
console.log("------------------------------------------------------------")
console.log("numbers: integers")
console.log("var x = 1")
var x = 1 // declare a variable 'x' with integer value '1'
console.log("x === 1 --->", x === 1) // should be 'true'
console.log("------------------------------------------------------------")
console.log("numbers: reals")
var x = 0.01 // declare a new variable 'x' with real value '0.01'
console.log("x === 0.01 --->", x === 0.01) // should be 'true'
console.log("------------------------------------------------------------")
console.log("strings:")
console.log('var x = "hello"')
var x = "hello" // strings of text in quotation marks
console.log('x === "hello" --->', x === "hello") // should be 'true'
console.log("var x = 'hello'")
var x = 'hello' // single quote marks are also string delimiters
console.log("x === 'hello' --->", x === 'hello') // should be 'true'
console.log("------------------------------------------------------------")
console.log("booleans:")
console.log("var x = true")
var x = true // boolean value 'true'
console.log("x === true --->", x === true) // should be 'true'
console.log("var x = false")
var x = false // boolean value 'false'
console.log("x === false --->", x === false) // should be 'true'
console.log("------------------------------------------------------------")
console.log("special values:")
console.log("var x = null")
var x = null // 'null' is a special value that means 'no value'
console.log("x === null --->", x === null) // should be 'true'
console.log("var x = undefined")
var x = undefined // 'undefined' is similar to 'null' but returns no value
console.log("x === undefined --->", x === undefined) // should be 'true'
console.log("------------------------------------------------------------")
console.log("objects: are collections of name/value or string-value pairs")
console.log('var thisTutorial = {topic: "WebPPL", year: 2018}')
var thisTutorial = { // object constructors are enclosed in curly braces
topic: "WebPPL", // the property ("slot") 'topic' has value "WebPPL"
year: 2018 // the property ("slot") 'year' has value 2018
}
console.log('thisTutorial !== {topic: "WebPPL", year:2018} --->',
thisTutorial !== {topic: "WebPPL", year:2018}) // should give 'true'
console.log('thisTutorial != {topic: "WebPPL", year:2018} --->',
thisTutorial != {topic: "WebPPL", year:2018}) // should give 'true'
console.log("object selectors: access the values of object properties")
console.log('thisTutorial.topic === "WebPPL" --->', thisTutorial.topic === "WebPPL")
console.log('thisTutorial["topic"] === "WebPPL" --->', thisTutorial["topic"] === "WebPPL")
console.log('thisTutorial.year === 2018 --->', thisTutorial.year === 2018)
console.log('thisTutorial["year"] === 2018 --->', thisTutorial["year"] === 2018)
console.log("------------------------------------------------------------")
console.log("arrays: are numerically indexed lists of values")
console.log("var primes = [2, 3, 5, 7]")
var primes = [2, 3, 5, 7]
console.log("primes !== [2, 3, 5, 7] --->", primes !== [2, 3, 5, 7])
console.log("primes != [2, 3, 5, 7] --->", primes != [2, 3, 5, 7])
console.log("primes[0] === 2 --->", primes[0] === 2) // first element with index 0
console.log("primes.length === 4 --->", primes.length === 4) // how many elements in array
console.log("primes[primes.length-1] === 7 --->",
primes[primes.length-1] === 7) // last element
console.log("var empty = []")
var empty = [] // ==> create an empty array with 0 elements
console.log("empty !== [] --->", empty !== [])
console.log("empty != [] --->", empty != [])
console.log("empty.length === 0 --->", empty.length === 0) // should be 'true'
console.log("------------------------------------------------------------")
console.log("nested objects:")
console.log('var myObject = {a:{c:"d"}, b:{e:"f"}}')
var myObject = {a:{c:"d"}, b:{e:"f"}}
console.log('myObject.b.e === "f" --->', myObject.b.e === "f")
console.log('myObject["b"]["e"] == "f" --->', myObject["b"]["e"] === "f")
console.log("------------------------------------------------------------")
console.log("nested arrays:")
console.log('var myArray = [["a", 11], ["b", 13]]')
var myArray = [["a", 11], ["b", 13]]
console.log('myArray !== [["a",11],["b",13]] --->', myArray !== [["a",11],["b",13]])
console.log('myArray != [["a",11],["b",13]] --->', myArray != [["a",11],["b",13]])
console.log('myArray[1][0] == "b" --->', myArray[1][0] == "b")
console.log('myArray[1][1] == 13 --->', myArray[1][1] == 13)
console.log("------------------------------------------------------------")
console.log("mixed objects:")
console.log("var myDataObject = {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]}")
var myDataObject = { // an object with two properties
trial1: [[1,2],[1,3]], // the value of each property is an array
trial2: [[2,4],[2,5]] // the elements of the arrays are arrays
}
console.log("myDataObject !== {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]} --->",
myDataObject !== {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]})
console.log("myDataObject != {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]} --->",
myDataObject != {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]})
console.log("myDataObject.trial2[0][0] == 2 --->", myDataObject.trial2[0][0] == 2)
console.log("myDataObject.trial2[1][1] == 5 --->", myDataObject.trial2[1][1] == 5)
console.log("------------------------------------------------------------")
console.log("mixed arrays:")
console.log("var myPoints = [{x:0, y:0}, {x:1, y:1}]")
var myPoints = // an array with two elements
[{x:0, y:0}, {x:1, y:1}] // each element is an object
console.log('myPoints !== [{"x":0,"y":0},{"x":1,"y":1}] --->',
myPoints !== [{"x":0,"y":0},{"x":1,"y":1}])
console.log('myPoints[1] !== {"x":1,"y":1} --->', myPoints[1] !== {"x":1,"y":1})
console.log('myPoints[1] != {"x":1,"y":1} --->', myPoints[1] != {"x":1,"y":1})
console.log('myPoints[0]["x"] == 0 --->', myPoints[0]["x"] == 0) // should be true
console.log("------------------------------------------------------------")
console.log("operators: operators act on values (= operands) to produce a value")
console.log("arithmetic operators:")
console.log("3 + 5 === 8 --->", 3 + 5 === 8) // should be true
console.log("3 - 5 === -2 --->", 3 - 5 === -2) // should be true
console.log("3 * 5 === 15 --->", 3 * 5 === 15) // should be true
console.log("3 / 5 === 0.6 --->", 3 / 5 === 0.6) // should be true
console.log("myPoints[0].y - myPoints[1].y === -1 --->",
myPoints[0].y - myPoints[1].y === -1) // more complicated operands also work
console.log('"3" + "2" === "32" --->', "3" + "2" === "32") // overloading of '+'
console.log("------------------------------------------------------------")
console.log("equality and relational operators:")
console.log("var x = 2; var y = 3")
var x = 2; var y = 3
console.log("equality '=='")
console.log("not equality '!='")
console.log("strict equality '==='")
console.log("not strict equality '==='")
console.log("(x == y) === false --->", (x == y) === false) // should be true
console.log("inequality operator '!='")
console.log("(x != y) === true --->", (x != y) === true) // should be true
console.log("relational operator '<'")
console.log("(x < y) === true --->", (x < y) === true) // should be true
console.log("(x <= y) === true --->", (x <= y) === true) // should be true
console.log("(x > y) === false --->", (x > y) === false) // should be true
console.log("(x >= y) === false --->", (x >= y) === false) // should be true
console.log('("two" === "two") === true --->', ("two" === "two") === true) // should be true
console.log('("two" == "three") === false --->', ("two" == "three") === false) // sh. be true
console.log('("two" > "three") === true --->', ("two" > "three") === true) // should be true
console.log('("two" >= "three") === true --->', ("two" >= "three") === true) // sh. be true
console.log("(false == (x > y)) --->", (false == (x > y)) === true )
console.log("------------------------------------------------------------")
console.log("logical operators:")
console.log("((x == 2) && (y == 3)) === true --->", ((x == 2) && (y == 3)) === true)
console.log("((x > 2) || (y < 3)) === false --->", (x > 2) || (y < 3) === false)
console.log("!(x == y) === true --->", !(x == y) === true)
console.log("------------------------------------------------------------")
console.log("")
console.log("function: ... a named and parametrized block of code that can be invoked")
console.log("var myPlus1 = function (x) {x + 1}")
var myPlus1 = function (x) {x + 1}
console.log("myPlus1(y) === 4, where y=3 --->", myPlus1(y) === 4)
console.log("var mySquare = function(x) {x * x}")
var mySquare = function(x) {x * x}
console.log("mySquare(myPlus1(y)) === 16, where y=3 --->", mySquare(myPlus1(y)) === 16)
console.log("------------------------------------------------------------")
console.log("")
console.log("methods: all JS objects have methods")
console.log("var a = []")
var a = [] // length(a) = 1
console.log(" a.push(...) ---> length(a'); a' = augmented a")
console.log("a.push(1,4,9,16) === 4 --->", a.push(1,4,9,16) === 4) // value = length(a') = 4
console.log(" array.pop() ---> removedElement(array)") // length(a'') = 3
console.log("a.pop() === 16 --->", a.pop() === 16) // value = removed element of array
console.log("a'' = ", a) // length(a'') = 3 ; a'' = [1, 4, 9]
console.log("a[0] === 1 --->", a[0] === 1) // first element of a'' === 1
console.log("(a[a.length-1]) === 9 --->", (a[a.length-1]) === 9) //last elmnt of a''[2] === 9
console.log("array.reverse() is an *inplace* reversal: array.reverse().reverse() ---> array")
console.log("a.reverse()[0] === 9 --->", a.reverse()[0] === 9) // *inplace* reversal: a'''
console.log("a''' = ", a) // length(a''') = 3 ; a''' = [9, 4, 1]
console.log("a.reverse()[2] === 9 --->", a.reverse()[2] === 9)// *inplace* reversal, again
console.log("a'''' = a'' = ", a) // length(a'''') = 3; a'''' = a''
console.log("a.shift() === 1 --->", a.shift() === 1)
console.log("a'''' = ", a) // length(a'''') = 2 ; // a'''' = [4, 9]
console.log("a[0] === 4 --->", a[0] === 4) // first element of a'''' === 4
console.log("(a[a.length-1]) === 9 --->", (a[a.length-1]) === 9)// last elmnt a''''[1] === 9
console.log("beware: a.push(1, 3, 7)[0] does not evaluate to a'''''[0] === 4 ")
console.log(" but to length(a''''') === 5")
console.log("a.push(1, 3, 7)[0] === 5 --->", a.push(1, 3, 7) === 5) // a'''''= [4, 9, 1, 3, 7]
console.log("(a[a.length-1]) === 7 --->", (a[a.length-1]) === 7)// last el. of a'''''[4] === 7
console.log("a''''' ---> ", a)
console.log("a'''''[4] === 7 ---> ", a[4] === 7)
console.log("------------------------------------------------------------")
console.log("")
console.log("var myPointsDist = function(p1, p2) { ")
console.log(" var a2 = Math.pow((p2.x - p1.x), 2) ")
console.log(" var b2 = Math.pow((p2.y - p1.y), 2) ")
console.log(" Math.sqrt(a2 + b2) ")
console.log("}")
console.log("var myPointsDist = function(p1, p2) {")
console.log(" var a2 = Math.pow((p2.x - p1.x), 2)")
console.log(" var b2 = Math.pow((p2.y - p1.y), 2)")
console.log(" Math.sqrt(a2 + b2)")
console.log("}")
var myPointsDist = function(p1, p2) { // because object methods are not allowed
var a2 = Math.pow((p2.x - p1.x), 2) // this function has to be different from Flanagan's
var b2 = Math.pow((p2.y - p1.y), 2) // object method
Math.sqrt(a2 + b2)
}
console.log("myPointsDist(myPoints[0], myPoints[1]) == 1.4142135623730951 --->",
myPointsDist(myPoints[0], myPoints[1]) == 1.4142135623730951)
console.log("------------------------------------------------------------")
console.log("")
console.log("conditional expressions:")
console.log("var myAbs = function(x) {(x >= 0) ? x : -x}")
var myAbs = function(x) {(x >= 0) ? x : -x}
console.log("myAbs(5) === 5 --->", myAbs(5) === 5)
console.log("myAbs(-5) === -5 --->", myAbs(-5) === 5)
console.log("===============================================================================")
Output JS in WebPPL
==============================================================================
file: 'PCM20180310_JS_in_WebPPL' by PCM *** version 2018/03/21 ***
This file contains JS test cases executable in WebPPL
*** beware, array methods are not referential transparent ! ****
WebPPL is a pure functional DSL (= Domain Specific language) embedded in JS
examples are similar but not identical to those in 'Core JavaScript',
ch.1.1 in David Flanagan 'JavaScript: The Definitive Guide', 2011. 6/e
==============================================================================
'console.log(...)' generates output in the browser's web console
comment: anything following double slashes '//' is a comment
the test template has this structure:
<stringOfTestDescription> '--->' <expression> <compOperator> <targetValue>
<stringOfTestDescription>, ... an informal description of the test
'--->', symbol with meaning '<expression> (left) evaluates to <value> (right)'
<expression>, ... a WebPPL-expression
<compOperator>, ... a comparison operator ==, !=, ===, !==, <, >, ...
<compOperator> '==' means a 'test of equality' (beware of type coercion !)
<compOperator> '===' means a 'test of strict equality'
<targetValue>, ... an expected value; should not deviate from <value> !
***important *** all tests should evaluate to ***true***
==============================================================================
variable: a variable is a symbolic name for a value
var pi = 3.141
pi === 3.141 ---> true
------------------------------------------------------------
numbers: integers
var x = 1
x === 1 ---> true
------------------------------------------------------------
numbers: reals
x === 0.01 ---> true
------------------------------------------------------------
strings:
var x = "hello"
x === "hello" ---> true
var x = 'hello'
x === 'hello' ---> true
------------------------------------------------------------
booleans:
var x = true
x === true ---> true
var x = false
x === false ---> true
------------------------------------------------------------
special values:
var x = null
x === null ---> true
var x = undefined
x === undefined ---> true
------------------------------------------------------------
objects: are collections of name/value or string-value pairs
var thisTutorial = {topic: "WebPPL", year: 2018}
thisTutorial !== {topic: "WebPPL", year:2018} ---> true
thisTutorial != {topic: "WebPPL", year:2018} ---> true
object selectors: access the values of object properties
thisTutorial.topic === "WebPPL" ---> true
thisTutorial["topic"] === "WebPPL" ---> true
thisTutorial.year === 2018 ---> true
thisTutorial["year"] === 2018 ---> true
------------------------------------------------------------
arrays: are numerically indexed lists of values
var primes = [2, 3, 5, 7]
primes !== [2, 3, 5, 7] ---> true
primes != [2, 3, 5, 7] ---> true
primes[0] === 2 ---> true
primes.length === 4 ---> true
primes[primes.length-1] === 7 ---> true
var empty = []
empty !== [] ---> true
empty != [] ---> true
empty.length === 0 ---> true
------------------------------------------------------------
nested objects:
var myObject = {a:{c:"d"}, b:{e:"f"}}
myObject.b.e === "f" ---> true
myObject["b"]["e"] == "f" ---> true
------------------------------------------------------------
nested arrays:
var myArray = [["a", 11], ["b", 13]]
myArray !== [["a",11],["b",13]] ---> true
myArray != [["a",11],["b",13]] ---> true
myArray[1][0] == "b" ---> true
myArray[1][1] == 13 ---> true
------------------------------------------------------------
mixed objects:
var myDataObject = {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]}
myDataObject !== {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]} ---> true
myDataObject != {trial1:[[1,2],[1,3]], trial2:[[2,4],[2,5]]} ---> true
myDataObject.trial2[0][0] == 2 ---> true
myDataObject.trial2[1][1] == 5 ---> true
------------------------------------------------------------
mixed arrays:
var myPoints = [{x:0, y:0}, {x:1, y:1}]
myPoints !== [{"x":0,"y":0},{"x":1,"y":1}] ---> true
myPoints[1] !== {"x":1,"y":1} ---> true
myPoints[1] != {"x":1,"y":1} ---> true
myPoints[0]["x"] == 0 ---> true
------------------------------------------------------------
operators: operators act on values (= operands) to produce a value
arithmetic operators:
3 + 5 === 8 ---> true
3 - 5 === -2 ---> true
3 * 5 === 15 ---> true
3 / 5 === 0.6 ---> true
myPoints[0].y - myPoints[1].y === -1 ---> true
"3" + "2" === "32" ---> true
------------------------------------------------------------
equality and relational operators:
var x = 2; var y = 3
equality '=='
not equality '!='
strict equality '==='
not strict equality '==='
(x == y) === false ---> true
inequality operator '!='
(x != y) === true ---> true
relational operator '<'
(x < y) === true ---> true
(x <= y) === true ---> true
(x > y) === false ---> true
(x >= y) === false ---> true
("two" === "two") === true ---> true
("two" == "three") === false ---> true
("two" > "three") === true ---> true
("two" >= "three") === true ---> true
(false == (x > y)) ---> true
------------------------------------------------------------
logical operators:
((x == 2) && (y == 3)) === true ---> true
((x > 2) || (y < 3)) === false ---> true
!(x == y) === true ---> true
------------------------------------------------------------
function: ... a named and parametrized block of code that can be invoked
var myPlus1 = function (x) {x + 1}
myPlus1(y) === 4, where y=3 ---> true
var mySquare = function(x) {x * x}
mySquare(myPlus1(y)) === 16, where y=3 ---> true
------------------------------------------------------------
methods: all JS objects have methods
var a = []
a.push(...) ---> length(a'); a' = augmented a
a.push(1,4,9,16) === 4 ---> true
array.pop() ---> removedElement(array)
a.pop() === 16 ---> true
a'' = 1,4,9
a[0] === 1 ---> true
(a[a.length-1]) === 9 ---> true
array.reverse() is an *inplace* reversal: array.reverse().reverse() ---> array
a.reverse()[0] === 9 ---> true
a''' = 9,4,1
a.reverse()[2] === 9 ---> true
a'''' = a'' = 1,4,9
a.shift() === 1 ---> true
a'''' = 4,9
a[0] === 4 ---> true
(a[a.length-1]) === 9 ---> true
beware: a.push(1, 3, 7)[0] does not evaluate to a'''''[0] === 4
but to length(a''''') === 5
a.push(1, 3, 7)[0] === 5 ---> true
(a[a.length-1]) === 7 ---> true
a''''' ---> 4,9,1,3,7
a'''''[4] === 7 ---> true
------------------------------------------------------------
var myPointsDist = function(p1, p2) {
var a2 = Math.pow((p2.x - p1.x), 2)
var b2 = Math.pow((p2.y - p1.y), 2)
Math.sqrt(a2 + b2)
}
var myPointsDist = function(p1, p2) {
var a2 = Math.pow((p2.x - p1.x), 2)
var b2 = Math.pow((p2.y - p1.y), 2)
Math.sqrt(a2 + b2)
}
myPointsDist(myPoints[0], myPoints[1]) == 1.4142135623730951 ---> true
------------------------------------------------------------
conditional expressions:
var myAbs = function(x) {(x >= 0) ? x : -x}
myAbs(5) === 5 ---> true
myAbs(-5) === -5 ---> true
===============================================================================