How do I do it in Ceylon - ceylon

I've the following code in Java and would like to port it in Ceylon.
public interface Condition {
Condition FALSE = facts->false;
Boolean evaluate(Fact<?> fact);
default Condition and(Condition other) {
return fact -> this.evaluate(fact) && other.evaluate(fact);
}
}
#Test void test() {
String str = "A String";
Condition a = fact -> !str.empty();
Condition b = fact -> str.contains("tr");
Condition both = a.and(b);
//expect(both(Fact('fact', str)), true);
}
So far I've tried using alias for the given code
shared alias Condition => Boolean(Fact<out Anything>);
Condition falseCondition = (Fact<out Anything> fact) => false;
shared interface ConditionComposer {
shared formal Boolean eval(Fact<out Anything> fact);
shared default Condition and(Condition other)<--**I want to pass a Condition here for the below to work** {
return (Fact<out Anything> fact) => this.eval(fact) && other.eval(fact);
}
}
I want to pass a Condition as a parameter to and() but as the eval() is part of ConditionComposer, the return statement won't compile. And how will I write a test case for this in Ceylon?

#Voiteh on gitter: ceylon/user advised the given solution.
shared interface Condition<Fact> {
shared static Condition<Fact> falseCondition => object satisfies Condition<Fact> {
shared actual Boolean evaluate(Fact fact) => false;
};
shared static Condition<Data> create<Data>(Boolean(Data) eval) => object satisfies Condition<Data> {
shared actual Boolean evaluate(Data fact) => eval(fact);
};
shared formal Boolean evaluate(Fact fact);
shared default Condition<Fact> and(Condition<Fact> other) => object satisfies Condition<Fact> {
evaluate(Fact fact) => this.evaluate(fact) && other.evaluate(fact);
};
shared default Condition<Fact> or(Condition<Fact> other) => object satisfies Condition<Fact> {
evaluate(Fact fact) => this.evaluate(fact) || other.evaluate(fact);
};
shared default Condition<Fact> not() => object satisfies Condition<Fact> {
evaluate(Fact fact) => !this.evaluate(fact);
};
}
shared void testConditions() {
value a = Condition.create<String>((String fact) => !fact.empty);
value b = Condition.create<String>((String fact) => fact.contains("str"));
value result = a.and(b).evaluate("A string");
assert (result);
print(result);
}
He further advised, "It could be simplified a bit if You would not pass condition to and and or but function reference like in create so it would be: "
interface Condition<Fact>{
shared static Condition<Fact> falseCondition => object satisfies Condition<Fact> {
shared actual Boolean evaluate(Fact fact) => false;
};
shared static Condition<Data >create<Data>(Boolean(Data) evala)=> object satisfies Condition<Data>{
shared actual Boolean evaluate(Data fact) => evala(fact);
};
shared formal Boolean evaluate(Fact fact);
shared default Condition<Fact> and(Boolean(Fact) other)=> object satisfies Condition<Fact>{
shared actual Boolean evaluate(Fact fact) => this.evaluate(fact) && other(fact);
};
shared default Condition<Fact> or(Boolean(Fact) other)=> object satisfies Condition<Fact>{
shared actual Boolean evaluate(Fact fact) => this.evaluate(fact) || other(fact);
};
shared default Condition<Fact> not=> object satisfies Condition<Fact>{
shared actual Boolean evaluate(Fact fact) => !this.evaluate(fact);
};
}
shared test void testConditions(){
value a=Condition.create<String>((String fact) => !fact.empty);
value b=((String fact)=> fact.contains("A"));
value result=a.and(b).evaluate("A string");
assert(result);
}
He further commented, "the second option wont work if You would b.and(a) because b is now just a function and not Condition
probably there is a way to make it less verbose but i don't know the syntax"

Related

How to avoid general Function type in angular

I'm using eslint and it states that using 'Function' as a type is unsafe.
Is there a better way of doing this, so that I don't use the function type:
I have this confirmation dialog that appears when I'm trying to delete something:
export class DialogConfirmationComponent {
message: string = "";
txtBtnConfirmation: string = "Confirm";
actionConfirm: Function = () => { };
actionCancel: Function = () => { };
}
And when I click on the confirm button on the html this actionConfirm Function is called.
I want it to be generic so that I can call this dialog for different components and uses, and define the action using bind on the component, like this:
export class ItemCardComponent {
constructor(
private dialog: MatDialog
) { }
public openDeleteDialog(item: Item): void {
const dialogRef = this.dialog.open(DialogConfirmationComponent, {
width: '500px',
panelClass: 'no-padding-dialog',
autoFocus: false
});
dialogRef.componentInstance.message= "Are you sure?";
dialogRef.componentInstance.txtBtnConfirmation = "Delete";
dialogRef.componentInstance.actionConfirm = this.delete.bind(this, item);
}
private delete(item: Item): void {
// ToDo: delete
}
}
So far it's working, but is there a better way of doing it without using the Function type?
You could use this if the function is very general and you are unsure of the number and type of parameters or the nature of the return type:
(...args: any[]) => any
However, if you are aware of the return type, you may use this in its place. Note that the return type in this case is void:
(...args: any[]) => void
If you want to boost type safety, you may also replace any with types. In this example, you are presuming that the parameters are of the type number or string and that the return type is unknown.
(...args: (string & number)[]) => unknown

count(): Parameter must be an array or an object that implements Countable in php 7.2.1

count(): Parameter must be an array or an object that implements Countable in php 7.2.1
using Yii2
How to resolve this issue?
public static function findAdminByUsername($username)
{
$adminUser = static::find()->where(['username' => $username,'userType'=>'ADMIN','user_status'=>self::STATUS_ACTIVE])->one();
if(count($adminUser)>0){
return $adminUser;
}else{
return null;
}
}
The thing is you are checking for count > 1 with using ->one() which looks odd, looking at your code you want to return NULL if there is no record found and if you look into documentation the function one() already returns NULL if there are no records found so you are adding extra code and it could easily be reduced to
public static function findAdminByUsername($username)
{
return static::find()->where(
[
'username' => $username,
'userType' => 'ADMIN',
'user_status' => self::STATUS_ACTIVE,
]
)->one();
}
You are using find()......->one()
so your query should return just an object .. without iteration capabilities.
if you want check if the find() return a value or not then you could check with isset. find()->one() return null if the query fail.
public static function findAdminByUsername($username)
{
$adminUser = static::find()->where(['username' => $username,'userType'=>'ADMIN','user_status'=>self::STATUS_ACTIVE])->one();
if( $adminUser !== null ){
return $adminUser;
}else{
return null;
}
}
if you don't need others that return the result for find()->..one() you could simply return
return static::find()->
where(['username' => $username,'userType'=>'ADMIN','user_status'=>self::STATUS_ACTIVE])
->one();

How to determine if a getter is defined before accessing it?

I have a set of get functions in JS such as:
get UserName() {
return this.userModel.Name;
}
I want the ability to check if the function exist before I call it.
I tried:
if (this.UserName == 'function')...
but it's always false, since userModel.name is a string, typeof UserName returns 'string' type and not a 'function'.
any idea how I can accomplish this ?
One simple way to check that UserName exists (without calling the getter) is to use in:
if ('UserName' in this) {
// this.UserName is defined
}
If you need a stronger check where you directly access the getter function, use Object.getOwnPropertyDescriptor:
var userNameDesc = Object.getOwnPropertyDescriptor(this, 'UserName');
if (userNameDesc && userNameDesc.get) {
// this.UserName is definitely a getter and is defined
}
You can use Object.getOwnPropertyDescriptor() which returns basically the same data structure that is fed to Object.defineProperty() like this:
let descriptor = Object.getOwnPropertyDescriptor(this, "UserName");
if (descriptor && typeof descriptor.get === "function") {
// this.UserName is a getter function
}
Or, if you want more granular info, you can do this:
let descriptor = Object.getOwnPropertyDescriptor(this, "UserName");
if (!descriptor) {
// property doesn't exist
} else if (typeof descriptor.get === "function") {
// this.UserName is a getter function
} else if (typeof descriptor.value === "function") {
// property directly contains a function (that is just a regular function)
} else {
// property exists, but it does not have a getter function and
// is not a regular function
}
You can also test many other properties of the descriptor such as value, set, writable, configurable, enumerable as described here on MDN.

basic reducer possibly mutating app state

I am using Redux spread operator to hopefully mantain the state as immutable objects.
However, i am managing to make the most simple unit test fail.
I assume the error probably has to do with immutables, but am i not using the spread operator correctly?
Here is my unit test:
describe('app logic', () => {
it('initialises app', () => {
const newState = reducer(INITIAL_STATE, {type: "NEXT"})
const expectState = {
start: true,
render_component: null,
requests: {},
results: {},
}
console.log('newState', newState)
console.log('expected state', expectState)
expect(newState).to.equal(expectState)
})
})
and here is my reducer
export const INITIAL_STATE = {
start: false,
render_component: null,
requests: {},
results: {}
}
export const next = (state) => {
if (state === INITIAL_STATE) {
return {
...state,
start: true,
}
}
return state
}
export function reducer(state = INITIAL_STATE, action) {
switch (action.type) {
case 'NEXT':
return next(state)
default:
return state
}
}
I print the two objects, and they look the same.
i get the error :
1) app logic initialises app:
AssertionError: expected { Object (start, render_component, ...) } to equal { Object (start, render_component, ...) }
Not sure exactly which testing library you are using, but usually a name like .equal is used to test strict equality ( === ), which means (at least in the case of objects) that the two things being compared must actually reference the exact same object. So, for example,
const original = { a: 1 }; // creates a new object, assign it
const testMe = { a: 1 }; // creates another new object, assign it
console.log( original === testMe ) // false
evaluates to false, because while the objects have the same content, they do not reference the exact same object. They are separate, independently created, objects that happen to have the same content. Compare that to
const original = {a: 1}; // create a new object
const testMe = original; // create another reference to the same object
console.log( original === testMe ); // true
So when you return
return {
...state,
start: true,
}
you are creating and returning a new object, so it naturally can not reference the same object that you created and assigned to the variable name expectedState.
If what you are interested in is not strict equality, but rather just that the content in the two objects are the same, there exists other methods than .equal, usually named something with deep (since they go deep into the objects/arrays/whatever to check if the values are the same).
Chai.js has examples of both expect(x).to.equal(y) and expect(x).to.deep.equal(y) in their docs: http://chaijs.com/api/bdd/#method_equal
Your testing library probably has very similar, if not identical, syntax.

Trouble implementing Summable

I'm trying to implement classes DistanceCM and DistanceMM, and I want these to be summable interchangeably, as long as they both inherit from Distance.
However, I get this error:
"Error:(46, 76) ceylon: type parameter 'Other' of declaration
'Summable' has argument 'Distance' which is not assignable to upper
bound 'Summable' of 'Other'"
...which I can't decipher... The error message refers to this line in the code below:
shared actual Distance plus(Distance other)
This is the current code:
abstract class Distance() of DistanceMM | DistanceCM {
shared formal Distance multiplyScalar(Float scalar);
}
class DistanceMM(variable Float val) extends Distance() satisfies Summable<Distance>
{
shared Float distanceInMillimeters;
shared Float distanceInCentimeters;
switch (unit)
case (millimeter) {
distanceInMillimeters => val;
distanceInCentimeters => val / 10;
}
case (centimeter) {
distanceInMillimeters => val * 10;
distanceInCentimeters => val;
}
shared actual DistanceMM multiplyScalar(Float scalar) {
val = val * scalar;
return this;
}
shared actual Distance plus(Distance other) {
switch (other)
case (DistanceMM) {
return DistanceMM(val + other.distanceInMillimeters(), unit);
}
case (DistanceCM) {
return DistanceMM(val + other.distanceInCentimeters(), unit);
}
}
}
class DistanceCM(variable Float val) extends Distance() satisfies Summable<Distance>
{
shared Float distanceInMillimeters;
shared Float distanceInCentimeters;
switch (unit)
case (millimeter) {
distanceInMillimeters => val;
distanceInCentimeters => val / 10;
}
case (centimeter) {
distanceInMillimeters => val * 10;
distanceInCentimeters => val;
}
shared actual DistanceCM multiplyScalar(Float scalar) {
val = val * scalar;
return this;
}
// implementation missing
}
interface Summable<Other> of Other​ given Other satisfies Summable<Other>
Notice the constraint (the given clause). You're claiming that DistanceMM satisfies Summable<Distance>, but Distance doesn't satisfy the constraint on Other (Distance doesn't satisfy Summable<Distance>). Try this:
interface Distance of Centimeter | Millimeter satisfies Summable<Distance> {}
class Centimeter() satisfies Distance {
shared actual Distance plus(Distance other) => nothing;
}
class Millimeter() satisfies Distance {
shared actual Distance plus(Distance other) => nothing;
}