How do I specify default values in DAML for primitive types and records? - daml

I don't see a way to specify a default value in DAML. Say I want to specify False as the default value for a Bool or the time now as the default value for a variable of type Time. How do I do that?

DAML does not provide a way to specify default values. However, you can create functions that set the defaults, e.g., let’s say you have a template T:
template T
with
p : Party
value : Int
where
signatory p
You can now define a function createT that will set value to 42:
createT : Party -> T
createT p = T with
p = p
value = 42
You can then overide the default using with-syntax, e.g.
(createT alice) with value = 43

Related

Alembic migration server default value is recognized as null when trying to update a column

I am trying to do a migration to update the value of the column has_bubble_in_countries based on the has_bubble_v1 s column value.
I created before the upgrade() the table:
subscription_old_table = sa.Table(
'Subscription',
sa.MetaData(),
sa.Column('id', sa.Unicode(255), primary_key=True, unique=True, nullable=False),
sa.Column('has_bubble_v1', sa.Boolean, nullable=False, default=False),
sa.Column('has_bubble_in_countries', MutableList.as_mutable(ARRAY(sa.Enum(Country))), nullable=False, default=[], server_default='{}')
)
And then the upgrade() method looks like:
def upgrade():
connection = op.get_bind()
for subscription in connection.execute(subscription_old_table.select()):
if subscription.has_bubble_v1:
connection.execute(
subscription_old_table.update().where(
subscription_old_table.c.id == subscription.id
).values(
has_bubble_in_countries=subscription.has_bubble_in_countries.append(Country.NL),
)
)
# Then drop the column after the data has been migrated
op.drop_column('Subscription', 'has_bubble_v1')
All the rows in the database of has_bubble_in_countries column have this value {} when I check the database using pgadmin's interface.
When the upgrade() function gets to the update method it throws this error:
sqlalchemy.exc.IntegrityError: (psycopg2.errors.NotNullViolation) null value in column "has_bubble_in_countries" of relation "Subscription" violates not-null constraint
DETAIL: Failing row contains (keydsakwlkad, null, 2027-08-14 00:00:00+00,groot abonnement, big, {nl}, null, null, 2022-08-08 08:45:52.875931+00, 3482992, {}, f, null, null, null, t, 2011-05-23 08:55:20.538451+00, 2022-08-08 09:10:15.577283+00, ***null***).
[SQL: UPDATE "Subscription" SET has_bubble_in_countries=%(has_bubble_in_countries)s::country[] WHERE "Subscription".id = %(id_1)s]
[parameters: {'has_bubble_in_countries': None, 'id_1': '1pwohLmjftAZdIaJ'}]
The bolded value from the error is the value that is retrieved for the has_bubble_in_countries column even if it has a server_default='{}' and nullable=False.
Is there any possibility to add a configuration to alembic to recognize the server default s value when it is retrieved from the database? Or how can this be fixed?
I think the problem is actually that are you passing in the result of .append() which is None. Unlike other languages where it is common to return the altered list, append changes the list in place. I'm not sure that is a great idea for a core query result here but it seems to work. Also as far as I know, if you pass in NULL it doesn't trigger the default. The default is used when you pass in no value at all either when inserting or updating.
with Session(engine) as session, session.begin():
for subscription in session.execute(subscription_old_table.select()):
if subscription.has_bubble_v1:
# Append here.
subscription.has_bubble_in_countries.append(Country.NL)
# Then set values:
session.execute(
subscription_old_table.update().where(
subscription_old_table.c.id == subscription.id
).values(has_bubble_in_countries=subscription.has_bubble_in_countries,
)
)
Maybe cloning the list and then adding the element like this would be safer and clearer:
has_bubble_in_countries=subscription.has_bubble_in_countries[:] + [Country.NL]

ServiceStack.OrmLite: StringLengthAttribute.MaxText produces "LONGTEXT" - how can I set to "TEXT"?

Using ServiceStack's OrmLite and decorating a Property with the following attribute, creates a column of type LONGTEXT, instead o TEXT as noted in the docs:
But it becomes LONGTEXT:
I tried setting the StringLenghtAttribute to something else, 65535, 70000, Int32.MaxValue etc, but it either interpretet it as a VARCHAR and gave me the Column length too big or Row size too large, or it became a LONGTEXT.
Question is: how can I force it to become "TEXT" (or any other text type in mysql)?
I could perhaps modify the MaxColumnDefinition and set it to TEXT but then I will never get LONGTEXT I assume.
Update
Setting the MaxColumnDefinition to TEXT didn't change a thing.
Can I decorate the class with an attribute, specifying the type somehow? Or is that too sql-version-specific?
Or perhaps I should override the GetColumnDefinition and implement my own logic...
(Please note that this solution produces other problems that I will ask in a separate SO post)
After some more research, it was solved creating my own StringConverter, as can be seen below:
public class MyStringConverter : StringConverter
{
public override string GetColumnDefinition(int? stringLength)
{
if (stringLength.GetValueOrDefault() == StringLengthAttribute.MaxText)
return MaxColumnDefinition;
if (stringLength.GetValueOrDefault(StringLength) <= 255)
{
return UseUnicode
? $"NVARCHAR({stringLength.GetValueOrDefault(StringLength)})"
: $"VARCHAR({stringLength.GetValueOrDefault(StringLength)})";
}
else if (stringLength.GetValueOrDefault(StringLength) <= 65535)
{
return $"TEXT";
}
else
{
return "LONGTEXT";
}
}
}
I also suggest setting the default StringLength to something smaller than the default 8000:
StringConverter converter = OrmLiteConfig.DialectProvider.GetStringConverter();
converter.StringLength = 255;
This way, the default string will be varchar(255). If you want to make a specific string property something else, then set the attribute according to the MyStringConverter:
type = typeof(tWorks.Core.CoreCommons.ContactModuleProtocols.SMS.ModuleSettingsSMS);
type.GetProperty(nameof(MyClass.Prop1)).AddAttributes(new StringLengthAttribute(255)); // ==> varchar(255)
type.GetProperty(nameof(MyClass.Prop2)).AddAttributes(new StringLengthAttribute(500)); // ==> TEXT
type.GetProperty(nameof(MyClass.Prop3)).AddAttributes(new StringLengthAttribute(70000)); // ==> LONGTEXT

Create 1 function from 2 other functions in scala?

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

how do I indicate an unset default parameter of type Number in Flex3?

for String and Object type, I can set the default parameter to null to indicate that it was not set by the caller. Is there a mechanism in flex3 to do the same for the Number type?
So for instance:
public function myMethod( stringVar:String=null, ObjectVar:Object=null, numberVar:Number )
{
...
}
I could do the following, but it just feels ugly
public function myMethod( numberVarObj:Object=null )
{
var numberVarSet:Boolean=true;
if( numberVarObj == null ) {
numberVarSet = false;
}
and then everywhere I want to use numberVar I can check for numberVarSet and cast as a Number.
I suppose you could always try:
var numberVar:* = null;
And then set it to a number when you want . . . It would be nice to have a solution that is strongly typed though.
Another option, as specified in Adobe's Docs (scroll down to default values), would be to treat the value NaN as null. However, if your data has ANY chance of containing a NaN value, this is a horrible idea.
I'd recommend the "ugly" solution you have, but if you really want another option you can use NaN and then use isNaN(num) to check the value.

Why can't typed optional arguments have a default of Null?

In ActionScript 3, when you declare an optional argument by giving it a default value, the value null cannot be used on typed arguments.
function Action(Param:int=null){
// 1184: Incompatible default value of type Null where int is expected.
}
function Action(Param:int=0){
// No compiler errors
}
Any workarounds for this, or general purpose values that can apply to all data types?
You can change your int to Number and then can set it to NaN which is a special number that means 'not a number' and this can represent your null state for a Number.
To check if something is NaN, you must use the isNaN() function and not val == NaN, or you will not get what you expect.
function Action(param:Number = NaN) : void {
trace(param);
}
For all other objects, you can set them to null, but 'primitive' numbers are handled differently in Actionscript.
int variables cannot be null, that's why you get that error, only reference types like objects can be null
Instead you can use NaN as a special number instead of null. If you want to check if something is NaN you mus use the isNaN function.
you could also include a flag in the method signature to avoid having the parameter promoted from int to number:
function whatever(intProvided:Boolean = false, someInt:int = 0):void
{
if(intProvided)
doSomeStuff();
}