Deconstructing a list of parameters in class constructor - Coffeescript - coffeescript

If I have a class that I pass a number of parameters to:
class Foo
constructor: (parameters) ->
#bar = parameters.bar
#moo = parameters.moo
The class is created like so:
foo = new Foo(bar: 2, moo: 8)
My question is what is the most elegant way to detect in the constructor if the variables being passed exist, and if not to set a default. The way I would do it in javascript would be:
this.bar = ( parameters.bar !== undefined ) ? parameters.bar : 10;
where 10 is the default.
Thanks for your help :)
Good answers - Just to summerize the best:
Inorder to detect if a parameter exists and define a default if it doesn't, in javascript is:
this.bar = ( parameters.bar !== undefined ) ? parameters.bar : 10;
and in coffescript is:
#bar = parameters.bar ? 10
So elegant and compact!

You can use the existential operator:
class Foo
constructor: (options = {}) ->
#bar = options.bar ? 10
#moo = options.moo ? 20
That constructor compiles to:
// Compiled JS.
function Foo(options) {
var _ref, _ref1;
if (options == null) {
options = {};
}
this.bar = (_ref = options.bar) != null ? _ref : 10;
this.moo = (_ref1 = options.moo) != null ? _ref1 : 20;
}
An equivalent alternative is to destruct the options object immediately (therefore avoiding an unnecessary name for it) and then setting the default values in case those options were not passed:
class Foo
constructor: ({#bar, #moo} = {}) ->
#bar ?= 10
#moo ?= 20
As passing an object with options is a common pattern in JS code, some libraries have useful utility functions that can help with this. Underscore, for example, provides _.defaults, which i think results in quite readable code:
class Foo
constructor: ({#bar, #moo} = {}) ->
_.defaults #, bar: 10, moo: 20
If you are not using Underscore, there is also $.extend (who doesn't use jQuery anyway?):
class Foo
defaults = bar: 10, moo: 20
constructor: (options = {}) ->
{#bar, #moo} = $.extend {}, defaults, options
An alternative is to extend the Foo object directly if you trust that the only options that will be passed are the valid ones (this results in quite minimal JS compared to the other ones):
class Foo
defaults = bar: 10, moo: 20
constructor: (options = {}) ->
$.extend #, defaults, options
And a final alternative is to have the default values in the Foo.prototype and only set them as own properties if they come in the options parameter:
class Foo
bar: 10
moo: 20
constructor: ({bar, moo} = {}) ->
#bar = bar if bar?
#moo = moo if moo?
This prevents all the instances of Foo from having separate properties of their own and instead shares the same properties between instances when they use the default values, the same that is usually done with methods. You can also do #bar = bar if #bar isnt bar to assign those properties only when the parameter value differs from the default value.
As you can see, there are quite a lot of ways to do this. None of them is perfect, they all have their pros and cons, so try to choose the one that better suits your needs/taste/whatever =D

You could do this using the ?= operator:
class Foo
constructor: (parameters) ->
#bar = parameters.bar
#bar ?= 10
#moo = parameters.moo
#moo ?= 20
If you didn't mind passing in positional arguments rather than a hash, you could also do this very elegantly using default parameter values:
class Foo
constructor: (#bar = 10, #moo = 20) ->
f = new Foo

You could define an object of defaults and do something like this..
(parameters = {}) ->
this[key] = parameters[key] ? defaults[key] for key, value of defaults
But you really don't have to go through all of that. The easiest way to make default values is just to use prototypal inheritance...
class Foo
bar: 10
moo: 10
constructor: (parameters = {}) ->
this[key] = value for own key, value of parameters
Assuming the above:
a = new Foo();
a.bar # => 10
b = new Foo(bar: 50)
b.bar # => 50
With the exception of the constructor every property you define with a : will become a property on the object's prototype.
The class definition translates to this JavaScript:
Foo = (function() {
Foo.prototype.bar = 10;
Foo.prototype.moo = 10;
//etcetc
return Foo;
})();
Play with it. Hope that helps.

There is a more simpler way:
class Foo
constructor: (parameters = {}) ->
{
#bar = 10
#moo = 20
} = parameters

The new version of coffeescript has a great way to solve this exact problem
class MyObject
constructor: ({string1='x', string2='y'} = {})
it works great with regular functions too
myFunction = ({string1='x', string2='y'} = {}) ->
string1 + string2
console.log myFunction({string1:"a", string2:"b"})
# outputs: 'ab'
console.log myFunction()
# outputs: 'xy'

Related

Defining Entity Framework Keys using Fluent API

I am trying to define a key for a model type that has two key properties and is defined like this:
type Model () =
member val IdOne = 0 with get, set
member val IdTwo = 0 with get, set
member val OtherProperty = "" with get, set
When I try to use this model in Entity Framework 5, I get the error that "Model has no key defined. Define the key for this EntityType". The model types are given, I cannot change them and add the [<Key>] attribute. So I tried the Fluent API.
In C#, you would do something like this:
modelBuilder.Entity<Model>().HasKey(m => new { m.IdOne, m.IdTwo });
It uses an anonymous type. But for the life of me I cannot figure out how to pull this off in F#. I tried Tuples, Records, even a regular type that has the properties IdOne and IdTwo:
// Regular type with properties IdOne & IdTwo.
type ModelKey (idOne, idTwo) =
member this.IdOne = idOne
member this.IdTwo = idTwo
modelBuilder.Entity<Model>().HasKey(fun (m : Model) -> ModelKey (m.IdOne, m.IdTwo))
// ArgumentNullException: Value cannot be null. Parameter name: source
// Regular type with default constructor and properties IdOne & IdTwo.
type ModelKey2 () =
member val IdOne = 0 with get, set
member val IdTwo = 0 with get, set
modelBuilder.Entity<Model>().HasKey(fun (m : Model) -> ModelKey2 ())
// ArgumentNullException: Value cannot be null. Parameter name: source
// Record type.
type ModelKeyRecord = { IdOne : Int32; IdTwo : Int32 }
modelBuilder.Entity<Model>().HasKey(fun (m : Model) -> { IdOne = m.IdOne; IdTwo = m.IdTwo })
// ArgumentNullException: Value cannot be null. Parameter name: source
// Tuple.
modelBuilder.Entity<Model>().HasKey(fun (m : Model) -> (m.IdOne, m.IdTwo))
// ArgumentNullException: Value cannot be null. Parameter name: source
None of these approaches work, I get an ArgumentNullException every time. I'm out of ideas...
EDIT
With the code Tomas provided below (that causes the same ArgumentNullException btw.), I did some snooping around. This is what I found:
I used the function below to analyze the Expression Tree C# is building:
static void Analyze<T>(Expression<Func<Model, T>> function)
{
}
// Call it like this:
Analyze(m => new { m.IdOne, m.IdTwo });
Then I looked at the generated lambda in the debugger. This is what C# generates:
{m => new <>f__AnonymousType0'2(IdOne = m.IdOne, IdTwo = m.IdTwo)}
Doing the same thing on the F# side using the getFuncTree function from Tomas using <# fun (m : Model) -> ModelKey(m.IdOne, m.IdTwo) #> yields:
{m => new ModelKey(m.IdOne, m.IdTwo)}
As you can see, the explicit naming of the - what is this anyway, looks like properties - arguments is missing in the F# code. I recreated the whole expression tree by hand in F# so that it would look like the C# version:
let modelKeyExpression =
Expression.Lambda<Func<Model, ModelKey>> (
body = Expression.New (
``constructor`` = typeof<ModelKey>.GetConstructor [| typeof<Int32>; typeof<Int32> |],
arguments = seq {
yield Expression.MakeMemberAccess (
expression = Expression.Parameter (
``type`` = typeof<Model>,
name = "m"
),
``member`` = typeof<Model>.GetProperty "IdOne"
) :> Expression;
yield Expression.MakeMemberAccess (
expression = Expression.Parameter (
``type`` = typeof<Model>,
name = "m"
),
``member`` = typeof<Model>.GetProperty "IdTwo"
) :> Expression
},
members = seq {
yield (typeof<ModelKey>.GetProperty "IdOne") :> MemberInfo
yield (typeof<ModelKey>.GetProperty "IdTwo") :> MemberInfo
}
),
parameters = [
Expression.Parameter (
``type`` = typeof<Model>,
name = "m"
)
]
)
The part that was missing in the F# representation is the members sequence.
When I move the mouse over this expression, this representation appears:
{m => new ModelKey(IdOne = m.IdOne, IdTwo = m.IdTwo)}
As you can see, apart from the class, it looks the same. But when I try to use this expression in the HasKey method, I get the following InvalidOperationException:
The properties expression 'm => new ModelKey(IdOne = m.IdOne, IdTwo= m.IdTwo)'
is not valid. The expression should represent a property: C#: 't =>
t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. When specifying multiple
properties use an anonymous type: C#: 't => new { t.MyProperty1,
t.MyProperty2 }' VB.Net: 'Function(t) New With { t.MyProperty1,
t.MyProperty2 }'.
So it seems to me that this anonymous class syntax does something special...
In F# 4.6, this has worked for me after much struggle.
Apperantly all you need is a tuple. Makes sense since an anon object without explicit member names is basically, a tuple.
I can't believe nobody has put this on the MS documentation tho.
modelBuilder.Entity<Entity>()
.HasKey(fun e -> (e.Key1, e.Key2) :> obj)
|> ignore
EDIT: The technique below would be needed in F# 2.0, but it should not be needed in the newer versions. There must be some other issue with the F#-generated expression tree...
I think the problem is that Entity Framework wants you to specify a lambda expression as an expression tree:
modelBuilder.Entity<Model>().HasKey(fun (m : Model) -> ModelKey (m.IdOne, m.IdTwo))
This should just work in F# 3.1 in Visual Studio 2013, but it is not supported in F# 3.0. You can still do this, but you'll have to use F# quotations and write a bit of code that converts a quotation to LINQ expression tree - there is a helper that does most of the work:
open System
open System.Linq.Expressions
open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Linq.RuntimeHelpers
let getFuncTree (quotation:Expr<'a -> 'b>) =
let e = LeafExpressionConverter.QuotationToExpression quotation
let call = e :?> MethodCallExpression
let lam = call.Arguments.[0] :?> LambdaExpression
Expression.Lambda<Func<'a, 'b>>(lam.Body, lam.Parameters)
getFuncTree <# fun x -> x + 1 #>
Using this, you should be able to call:
modelBuilder.Entity<Model>().HasKey(getFuncTree <# fun (m : Model) ->
ModelKey (m.IdOne, m.IdTwo) #>)
You could define an extension method like HasKeyQuot that does this behind the cover, to make the code a bit nicer.
It looks like the issue is twofold:
F#'s compiler never sets the Members collection of a LINQ NewExpression during quotation translation, but this is used to mark the construction of an anonymous type, which EF expects.
EF is really picky: even in C#, doing m => new { A = m.IdOne, B = m.IdTwo } won't work - the anonymous type's property names must match the model's property names.
One way to work around the issue (which is probably overkill, but works) is to create a new type dynamically at runtime which has fields with the right names and then just use a tuple in the F# code:
open Quotations.Patterns
open Quotations.ExprShape
open System.Reflection
open System.Linq.Expressions
module AnonymousTypeFixer =
let private mb =
let ab = System.AppDomain.CurrentDomain.DefineDynamicAssembly(AssemblyName("codeGen"), Emit.AssemblyBuilderAccess.ReflectionOnly)
ab.DefineDynamicModule("codeGen")
let transform (Lambda(v, (NewTuple exprs)) : Quotations.Expr<'a -> 'b>) =
let newV = Expression.Variable(v.Type, v.Name)
let cvtExpr (PropertyGet(Some(Var v'), p, [])) =
assert (v = v')
Expression.Property(newV, p) :> Expression, p
let ty = mb.DefineType(v.Type.Name)
let ctor = ty.DefineConstructor(MethodAttributes.Public (*||| MethodAttributes.RTSpecialName ||| MethodAttributes.SpecialName*), CallingConventions.HasThis, exprs |> List.map (fun e -> e.Type) |> List.toArray)
ctor.GetILGenerator().Emit(Emit.OpCodes.Ret)
let fields =
[for (_, p) in exprs |> List.map cvtExpr ->
ty.DefineField(p.Name, p.PropertyType, FieldAttributes.Public) :> MemberInfo]
ty.CreateType()
let newE = Expression.New(ctor, exprs |> Seq.map (cvtExpr >> fst), fields)
Expression.Lambda<System.Func<'a, obj>>(newE, newV)
let mb = System.Data.Entity.DbModelBuilder()
mb.Entity<Model>().HasKey(AnonymousTypeFixer.transform <# fun (m:Model) -> m.IdOne, m.IdTwo #>)
// F# 3.0
open Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter
// Regular type with properties IdOne & IdTwo.
type ModelKey (idOne, idTwo) =
member this.IdOne = idOne
member this.IdTwo = idTwo
modelBuilder.Entity<Model>()
.HasKey(QuotationToLambdaExpression(
<# Func<_,_>(fun m -> NewAnonymousObjectHelper<_>(ModelKey(m.IdOne, m.IdTwo))) #>
)
)

In Coffeescript, can I call the constructor for an object after it has already been created?

In Coffeescript, can I call the constructor for an object after it has already been created? Like this:
class Snake
constructor: (#name) ->
obj = new Snake()
// do stuff
obj.constructor("Python")
Yes, you can. CoffeeScript class syntax is just syntax sugar for JavaScript constructor functions, which are just normal functions that you can call:
class Example
count: 0
constructor: (#name) ->
#count += 1
e = new Example 'foo'
console.log e.count # -> 1
console.log e.name # -> foo
# Call contructor again over the same instance:
Example.call e, 'bar'
console.log e.count # -> 2
console.log e.name # -> bar
# If you don't have the constructor in a variable:
e.constructor.call e, 'baz'
console.log e.count # -> 3
console.log e.name # -> baz
This code is compiled to:
var Snake, obj;
Snake = (function() {
function Snake(name) {
this.name = name;
}
return Snake;
})();
obj = new Snake();
So there is no constructor() method, coffeescript is just using it to generate the Snake() function.
So no you can't. But why would you want to do that if your code is object oriented?

Can I copy a closure in Scala?

This is perhaps a half-baked idea, but can I copy the environment of an expression? Consider the following example:
class foo[T](block: => T) {
var data = { () => block }
def run() = { data() }
}
var a = 5
var b = new foo({ a += 1; println(a) })
var c = new foo({ a += 1; println(a) })
b.run()
c.run()
b.run()
c.run()
I get the following output:
6
7
8
9
But what I really want is the following:
6
6
7
7
In short, I want foo to have copies of the variables in the block instead of referring to them, once the initial value has been resolved. Can this be done? scala.util.DynamicVariable seems promising, but I'm having a hard time understanding how I might use it in the example above.
If you want to make a copy, then why not make a copy?
var c = new foo({ var aa = a + 1; println(aa) })
If you want to take an existing closure that refers to a variable, and turn it into a closure that refers to a copy of that variable, then I'm afraid it's not possible.
In any case, mutable variables should not be used except in very rare circumstances and in a very controlled manner. That is, not juggling their references.
I think your problem is that you're closing over a (and thus changing its value as your program runs), rather than closing over a different variable initialized from a. You might want to try something more like this:
class bar[T](block: (T) => T, a: T) {
var cur = a
def run() = { cur = block(cur); cur }
}
var a = 5
var b = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
var c = new bar((r: Int) => { val q = r + 1; println(q); q }, a)
b.run()
c.run()
b.run()
c.run()
Output:
6
6
7
7
However, note that unlike your code, this will not affect the value of the a variable as it runs.
1) As n.m. already mentioned, you should prefer immutable concepts when using closures.
2) On the other hand this is exactly what closures are for. They don't capture the value of the variabe, they capture the variable itself! Your question is kinda upside-down. You actually are capturing the environment - the environment of your variable. If you don't need the same variable than copy it as n.m. or Ian McLaird respectively suggested.

Scala Properties Question

I'm still learning Scala, but one thing I thought was interesting is that Scala blurs the line between methods and fields. For instance, I can build a class like this...
class MutableNumber(var value: Int)
The key here is that the var in the constructor-argument automatically allows me to use the 'value' field like a getter/setter in java.
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
If I want to add constraints, I can do so by switching to using methods in place of the instance-fields:
// require all mutable numbers to be >= 0
class MutableNumber(private var _value: Int) {
require(_value >= 0)
def value: Int = _value
def value_=(other: Int) {
require(other >=0)
_value = other
}
}
The client side code doesn't break since the API doesn't change:
// use number...
val num = new MutableNumber(5)
num.value = 6
println(num.value)
My hang-up is with the named-parameter feature that was added to Scala-2.8. If I use named-parameters, my API does change and it does break the api.
val num = new MutableNumber(value=5) // old API
val num = new MutableNumber(_value=5) // new API
num.value = 6
println(num.value)
Is there any elegant solution to this? How should I design my MutableNumber class so that I can add constraints later on without breaking the API?
Thanks!
You can use the same trick that case classes do: use a companion object.
object Example {
class MutableNumber private (private var _value: Int) {
require (_value >= 0)
def value: Int = _value
def value_=(i: Int) { require (i>=0); _value = i }
override def toString = "mutable " + _value
}
object MutableNumber {
def apply(value: Int = 0) = new MutableNumber(value)
}
}
And here it is working (and demonstrating that, as constructed, you must use the object for creations, since the constructor is marked private):
scala> new Example.MutableNumber(5)
<console>:10: error: constructor MutableNumber cannot be accessed in object $iw
new Example.MutableNumber(5)
^
scala> Example.MutableNumber(value = 2)
res0: Example.MutableNumber = mutable 2
scala> Example.MutableNumber()
res1: Example.MutableNumber = mutable 0
Thanks for the answer! As an aside, I think the Scala-guys might be aware that there's an issue:
What's New in Scala 2.8: Named and Default Parameters
...
Until now, the names of arguments were a somewhat arbitrary choice for library developers, and weren't considered an important part of the API. This has suddenly changed, so that a method call to mkString(sep = " ") will fail to compile if the argument sep were renamed to separator in a later version.
Scala 2.9 implements a neat solution to this problem, but while we're waiting for that, be cautious about referring to arguments by name if their names may change in the future.
http://www.artima.com/scalazine/articles/named_and_default_parameters_in_scala.html
class MutableNumber {
private var _value = 0 //needs to be initialized
def value: Int = _value
def value_=(other: Int) {
require(other >=0) //this requirement was two times there
_value = other
}
}
you can modify all members of any class within curly braces
val n = new MutableNumber{value = 17}

initialise a var in scala

I have a class where I like to initialize my var by reading a configfile, which produces intermediate objects/vals, which I would like to group and hide in a method.
Here is the bare minimum of the problem - I call the ctor with a param i, in reality a File to parse, and the init-method generates the String s, in reality more complicated than here, with a lot of intermediate objects being created:
class Foo (val i: Int) {
var s : String;
def init () {
s = "" + i
}
init ()
}
This will produce the error: class Foo needs to be abstract, since variable s is not defined. In this example it is easy to solve by setting the String to "": var s = "";, but in reality the object is more complex than String, without an apropriate Null-implementation.
I know, I can use an Option, which works for more complicated things than String too:
var s : Option [String] = None
def init () {
s = Some ("" + i)
}
or I can dispense with my methodcall. Using an Option will force me to write Some over and over again, without much benefit, since there is no need for a None else than to initialize it that way I thought I could.
Is there another way to achieve my goal?
var s : Whatever = _ will initialize s to the default value for Whatever (null for reference types, 0 for numbers, false for bools etc.)
Instead of creating separate methods for initialization, you should perform the initialization using the following way :
class Foo(val i: Int) {
var s: String = {
var s0 = " "
s0 += i
// do some more stuff with s0
s0
}
var dashedDate = {
val dashed = new SimpleDateFormat("yy-MM-dd")
dashed.format(updated)
}
// Initializing more than one field:
var (x, y, z) = {
var x0, y0, z0 = 0
// some calculations
(x0, y0, z0)
}
}
Honestly, why are you using var? Why not just do:
val rootObject = readFile(filename)
This would make the most sense to me.