The specification has the following line
Let hasParameterExpressions be ContainsExpression of formals.
This line refers to the following:
14.1.5 Static Semantics: ContainsExpression
FormalParameters:[empty]
Return false.
FormalParameters:FormalParameterList,FunctionRestParameter
If ContainsExpression of FormalParameterList is true, return true.
Return ContainsExpression of FunctionRestParameter.
FormalParameterList:FormalParameterList,FormalParameter
If ContainsExpression of FormalParameterList is true, return true.
Return ContainsExpression of FormalParameter.
I don’t quite understand how all the above instructions should apply. For example, we have 3 parameters (a, b = 5, c). The final step in calculating FormalParameter will be
SingleNameBinding:BindingIdentifier
Return false.
SingleNameBinding:BindingIdentifierInitializer
Return true.
But I do not understand how I should read this:
FormalParameterList:FormalParameterList,FormalParameter
If ContainsExpression of FormalParameterList is true, return true.
Return ContainsExpression of FormalParameter.
Given an input of a, b = 5, c, the grammar would break down as
1. FormalParameters(a, b = 5, c)
|
2. FormalParameterList(a, b=5, c)
|------------------------------------------------
| |
3. FormalParameterList(a, b=5) , FormalParameter(c)
|------------------------- |
| | |
4. (FormalParameterList(a), FormalParameter(b=5)) , FormalParameter(c)
| | |
5. ((FormalParameter(a)) , FormalParameter(b=5)) , FormalParameter(c)
The grammar is defined here as a recursive structure. You could keep drilling down and expanding FormalParameter to get to Identifer and so on, but hopefully this is enough of an example.
So to calculate ContainsExpression, you can see that the first rule, as you recurse down this tree that matches is
FormalParameterList: FormalParameterList , FormalParameter
If ContainsExpression of FormalParameterList is true, return true.
Return ContainsExpression of FormalParameter.
because you can see that on 2&3 that it is a FormalParameterList made up of another FormalParameterList, a comma, and then a FormalParameter.
If you think of this like an tree, you can imagine this function as
function ContainsExpression(node) {
if (node.type === "FormalParameterList") {
// Step 1
if (ContainsExpression(node.left)) return true;
// Step 2
return ContainsExpression(node.right);
}
// ...
}
so that will recurse down the left and right side of each FormalParameterList. It is essentially a depth-first search through the tree, terminating as soon as something returns true.
That means that eventually ContainsExpression will recurse down until the node argument is FormalParameter. We then get to ContainsExpression for Bindings because FormalParameter is defined as BindingElement, which has
BindingElement: SingleNameBinding Initializer
Return true.
so eventually the recursion above will call ContainsExpression for FormalParameter(b=5)), and since b = 5 matches SingleNameBinding Initializer, ContainsExpression will return true. Then the depth-first search is done.
Related
So I have a function like so:
function foo(a, b, c=0, d=10, e=false) {
// ...
}
I would like to call this function with specific inputs, but not necessarily need to list them in order in the input. So like:
foo("bar", "skurr", e=true);
I know in python you can call functions this way, but it seems there is another method I am unaware of for js.
I have tried inputting an object but that did not work since it just uses the object as the first parameter of the function.
foo({a: "bar", b: "skurr", e: true});
How do I call functions in this manner in JavaScript?
One option uses the "object as first argument" as you've described, but the syntax is a bit odd. Consider:
function foo({a, b=0}) { console.log(a,b); }
This defines a function which requires an object as a first argument, and imposes structural constraints on that object. In particular, the following will work:
foo({a:1}); // output: 1 0
foo({a:1, b:2}); // output: 1 2
foo({}); // output: undefined 0
foo({a:1, b:2, c: 3}); // output: 1 2 /* c is ignored */
While the following will throw an error:
foo(); // TypeError: Cannot destructure property `a` of 'undefined' or 'null'
Another option, which is something you see a lot, is an idiom of the form:
function foo(some_object) { let {a,b} = some_object; console.log(a,b); }
Both of these are instances of destructuring. As far as I know it's the closest you'll get to python-like syntax (this answer gives perhaps some more exposition and I give a perhaps too thorough analysis of the formal language which explains the observed effects ES6 destructuring object assignment function parameter default value)
You can specify undefined for the values you want to default. This works because omitted values are also undefined. In your case, this would be:
function foo(a, b, c = 0, d = 10, e = false) {
// ...
}
// call:
foo("bar", "skurr", undefined, undefined, true);
Note that the above example is bad practice. If you have more than a few parameters (arguments), you should consider using objects and destructuring instead:
function foo({a, b, c = 0, d = 10, e = false} = {}) {
// ...
}
// call:
foo({a: "bar", b: "skurr", e: true});
Feature or bug: All empty Immutable.Lists test as identical.
For example:
var xxx = new Immutable.List();
var yyy = new Immutable.List();
xxx === yyy; // true
var zzz = yyy.push(1).pop();
zzz === yyy; // true
zzz = Immutable.fromJS([]);
xxx === zzz; // true
I can see why you might want to consider all empty lists as identical, but I also have use cases where just because 2 lists are empty doesn't imply that they are the same. As a counter-example, if I create two Immutable.Lists with the same contents, they do not test as identical.
Is there a way to tell 2 empty Lists apart?
Do you think this is a bug?
I am not an expert in Immutable.js nor a contributor, but I will try to write down some thoughts in immutable data structures.
Immutable.js is optimized for performance. Especially for performing equality checks. The idea behind immutable is, that if we have immutable data structures, we can determine if a structure changed simply by comparing the references. The first thing the implemention of Immutable.is does is checking if the references are equal:
export function is(valueA, valueB) {
if (valueA === valueB || (valueA !== valueA && valueB !== valueB)) {
return true;
}
// ...
}
If they are the same, we can always assume that the structure is still the same, since it is immutable. Making all empty lists equal increases performance here.
What we also need to understand is, that immutable data structures are widely used in functional programming languages (Immutable.js is actually inspired by Scala and Closure). Functional programming languages are much closer to mathematics than other languages. Mathematics is value based, this means in mathematics there are no instances. We would assume that a set containing the elements 1, 2 and 3 is equal a set of 1, 2 and 3. The empty set is always equal the empty set. The empty list equals the empty list.
Some interesting results from the Scala REPL:
scala> List(1, 2, 3) == List(1, 2, 3)
res0: Boolean = true
scala> Nil == Nil
res1: Boolean = true
scala> 1 :: 2 :: 3 :: Nil == List(1, 2, 3)
res2: Boolean = true
This is my code im trying to check if a list can be paritially identical into another. It is a game of dominoes a Domino=(Int,Int) and a Board = [Domino] and an end either left or right. I'm to check if any domino goes into a board say for example can domino (2,3) go into board [(3,4)(5,6)] is should be able to go to the left end because (2,3) and (3,4) have have a similar element. Here is my code
goesP :: Domino -> Board -> End -> Bool
goesP (h,t) [(h1,t1)] LeftEnd
| h==h1 || t==h1 =True
| otherwise False
goesP (h,t) [(h1,t1)] RightEnd
| h==t1 || t==t1 = True
| otherwise False
The pattern-matching you're using for the board is incomplete. The [(h1,t1)] pattern will only match Boards with one element (a pair (h1,t1)).
This is the same as using the pattern (h1,t1):[], ie. a list (:) containing the element (h1,t1) followed by an empty list [].
If we try to run your code with the examples you gave, (2,3) and [(3,4), (5,6)] (NOTE: you need a comma between the list elements!) we will get the following:
goesP (2,3) [(3,4), (5,6)] LeftEnd
Haskell will try to match these arguments against the patterns in your definition, from top to bottom.
It will check the following pattern first:
goesP (h,t) [(h1,t1)] LeftEnd
The first and third arguments will match, by 'unifying' h with 2, t with 3 and LeftEnd with LeftEnd, but the second will fail to match. The argument [(3,4), (5,6)] is 'syntactic sugar' for the list (3,4):(5,6):[], whilst the pattern [(h1,t1)] is syntactic sugar for the list (h1,t1):[]. We could unify h1 with 3 and t1 with 4, but there's nothing to unify (5,6) with.
Haskell will move on to the next possibility:
goesP (h,t) [(h1,t1)] RightEnd
The first argument will match (with h as 2 and t as 3), but the second argument will fail for the same reason as the previous clause. The third argument will also fail to match, since LeftEnd and RightEnd are different values (but that's the point ;) ).
Haskell will then see that there are no more possibilities, so the program will crash.
To fix this, you need to change the patterns for the second arguments so that Boards with more than one Domino are handled properly.
The case for LeftEnd is quite easy, just change the list of one element (h1,t1):[] to a list of at least one element (h1,t1):_ (I also added the extra = after otherwise):
goesP (h,t) ((h1,t1):_) LeftEnd
| h==h1 || t==h1 = True
| otherwise = False
The case for RightEnd is harder, since we want to compare with the last element of the list, but we only have access to the first. In this case, we can keep your definition which checks single-element lists, but also add another definition which uses recursion: if the list has more than one element, remove the first element and check it again. That way, any non-empty list will eventually be broken down until it only has one element, which your existing pattern can work with (again, I've added a missing =):
goesP (h,t) [(h1,t1)] RightEnd
| h==h1 || t==h1 = True
| otherwise = False
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
Now Haskell will match [(3,4), (5,6)] (which is sugar for (3,4):(5,6):[]) against (h1,t1):[]. This will fail, since the lists have different lengths. It will then match [(3,4), (5,6)] against _:xs, which will succeed, unifying xs with (5,6):[]. We then run the function again, using xs. This time the (5:6):[] will unify with the (h1,t1):[], so we can check whether the numbers are equal or not.
Also, an observation: goesP is actually overly complicated. You're using "pattern guards" to choose between the value True and the value False; however, pattern guards also require a Bool to work with. In other words, code like this:
| h==h1 || t==h1 = True
| otherwise = False
Can be read as saying "Create the Bool value h==h1 || t==h1; if it is True, then return True. If it is False then return False."
Clearly this is redundant: we can just return the value h==h1 || t==h1:
goesP (h,t) ((h1,t1):_) LeftEnd = h==h1 || t==h1
goesP (h,t) [(h1,t1)] RightEnd = h==h1 || t==h1
goesP (h, t) (_:xs) RightEnd = goesP (h, t) xs RightEnd
UPDATE: Fixed my RightEnd code
This question relates to the scala course from coursera so I want to please ask you to not give me the plain solution that I can copy-paste as this would break the coursera honor code.
This relates to the second assignment.
def Set = Int => Boolean
As it can be seen, Set is a function which returns weather or not the given int is or not part of the set. This is plain and simple so far. However the task asks me to create a union
def union(f: Set, s: Set): Set = ???
This union should return a set that satisfies the condition of both sets.
How could I do something like this:
I thought that such a thing could be done by adding the functions together however the following code:
f + s
Will not compile properly as expected
My question to is:
How would I be able to create a function from 2 other functions?
x => if x == 0 true else false //first
x => if x == 1 true else false //second
And what should equal:
x => if x==0 || x == 1 true else false
I'm not asking for a solution but rather how would I go around building something like this?
As I think you already understand, these Sets are functions that test whether a value meets the criteria for each Set.
The union of such a Set must also be a function that returns a Boolean (as shown by the type signature)
def union(f: Set, s: Set): Set
which (because Set is a type alias) is equivalent to:
def union(f: Int => Boolean, s: Int => Boolean): Int => Boolean
In plain English, union of two sets A and B means: "is the item in A or B".
Your task is to write a function that carries out that plain English specification.
You cannot "add" two functions together (at least, not in a way that is applicable to this question), but you can combine their results.
The Set has form of Set = Int => Boolean. Given the Int function will return true if the value is in a Set.
Well if we want to create a singleton set, we will return new function, which will compare any value passed to it, with the one passed to the function that created it.
The union of two sets, is one set plus the other. It means the element you're looking for must be either in one or the other set. But how do we get the new set, well we return a new function that does just that - checks if an element is either in one set or another.
Remember that in Scala functions can return functions, which may be evaluated later. I think that's the key.
The Set is defined as a function from Int to Boolean, "summing" two Sets won't return a Set object, the union means that one element should be either in one or in the other set but always expressed as a function.
I hope this is not too much, but given an element it should satisfy either f or s.
First of all, it's type Set =. Not def. Set is a type alias not a function definition.
Now, your question. You need a function which, when given two Int =>Boolean combines them with OR and returns a Int => Boolean.
First, how would you do this for two Boolean arguments?
def or(a: Boolean, b: Boolean) = a || b
So now we're half way there. What we have:
A pair of Int => Boolean functions.
A function that takes two Booleans and return a Boolean.
So all we need to do is apply each Set to an Int to get a Boolean and OR the result. The confusion is probably here.
The easiest way to curry a function is to do it explicitly
def union(f: Set, s: Set): Set = {
def doUnion(x: Int) = //apply x to f and s, return OR
doUnion
}
But we can, in Scala, so this inline by declaring an anonymous function
def union(f: Set, s: Set): Set = x => //apply x to f and s, return OR
I am using BND annotations to assist with creating a configuration managed by OSGI cm.
Here is my simple config
#Meta.AD(required = false, type = Type.Boolean, deflt = "false")
boolean enabled();
I have used the BND configuration annotation library quite a few times, but this is the first time that I would like to use a boolean type.
I have read through this
And it talks about an integer or other alternative number based handling of booleans for convenience. The thing is the deflt method always returns a string value, if my type was an integer I would do "2" (these are parsed). But booleans don't seem to be parsed in the configurable BND code up to this assignment point.
if (resultType == boolean.class || resultType == Boolean.class) {
if ( actualType == boolean.class || actualType == Boolean.class)
return o;
if (Number.class.isAssignableFrom(actualType)) {
double b = ((Number) o).doubleValue();
if (b == 0)
return false;
else
return true;
}
return true;
I would like to further know why this returns true when the deflt value is never even parsed. I expected this to more closely follow the spec and return false, since cm would try to do Boolean.parseFrom, so anything not "true" equal ignore case is false.
All of this isn't a complete failure because if I change the value through cm it works correctly after setting to true, and then false again, but obviously that was just an effort at wondering if it would ever work.
Simply I would like to know if anyone knows how to set a BOOLEAN default value using BND's configuration annotations.
Thanks