I am writing DSL (domain specific language for my code).
The code is:
class NeuronGroupDSL(identifier: String)(implicit network: N2S3SimulationDSL ) // declared values which must be provided by the user, [we can just give a default constructor to this]
{
implicit val sizeDefault : Int = 28 // added the implicit default value for the setNumberOfNeurons method
val id: String = identifier // We can add a default constructor with the Id and the network to this too allow user to skip this part
var neuronGroup: Option[NeuronGroupRef] = None // this variable stores all the information by using the get property and a associated function with it
private var neuronParameters: Seq[(Property[_], _)] = Seq()
private var neuronModel: NeuronModel = _
/**Properties of the NeuronGroupDSL **/
// Added a default size to the size variable
def ofSize(implicit size: Int): NeuronGroupDSL = {
this.neuronGroup.get.setNumberOfNeurons(size)
this
}
// Give user the opportunity to choose the type of available models by the help of pattern matching
/**Neuron Model:
1. Linear leaky integrate-and-fire model
2. FitzHugh-Nagumo model
3. Izhikevich model
**/
def modeling(model: NeuronModel): NeuronGroupDSL = {
this.neuronModel = model
this.neuronGroup.get.setNeuronModel(model, this.neuronParameters)
this
}
//we can define a default property the neuron group model here
def withParameters(properties: (Property[_], _)*): NeuronGroupDSL = {
this.neuronParameters = properties
this.neuronGroup.get.setNeuronModel(this.neuronModel, properties)
this
}
}
As you can see the definitions ofSize modeling withParameters have the same return type, so is it possible to implicitly define their return type and define these functions without their return part ?
Please help me I want to minimize the code as much as possible.
I too want to know that is it possible to use case class , concise lambda syntax in this code to further minimize it.
You can simply drop the return type, it will be inferred automatically:
def ofSize(implicit size: Int) = {
neuronGroup.get.setNumberOfNeurons(size)
this
}
Related
I want to do something I feel is simple, but I cannot figure out the way to do it. It is the following: according to some String variable I want to create an object of some specific type. However, the underlying objects have the same methods, so I want to be able to use this object outside the if block where the object is created. What is the best possible way to achieve it?
To ilustrate my need, here is the code:
var model = null
if (modelName == "KMeans") {
model = new KMeans()
} else if (modelName == "BisectKMeans") {
model = new BisectingKMeans()
}
model.setK(k)
model.fit(data)
Both KMeans and BisectingKMeans have the setK and fit methods. I want to create the object inside the if block but use the object outside it. This code gives an error when declaring the variable, as I'm not initializing it.
I've tried generic objects with a case class and declaring the variable as Any type, but cannot manage to get this to work, what is the best way to achieve what I'm looking for?
Scala actually does allow you to do this with structural types:
type Model = {
def setK(k: Int): Any
// the links in the question don't have a fit method
def fit(???): ???
}
val model: Model = if (modelName == "KMeans") { new KMeans() } else { model = new BisectingKMeans() }
model.setK(k)
model.fit(data)
But it isn't particularly recommended to use if you have better alternatives due to use of reflection. I would simply call setK and fit inside the blocks in this specific case; or if not, create your own wrappers of KMeans and BisectingKMeans which implement a common trait.
create your own interface and adapt the implementation to that. This will also work if you need to unify very different classes (different method names for example) into a common interface. Using implicit def is not required but does save the wrapping part at the call site
trait Model {
def setK(): ??? // fill in your type
def fit(): ??? // fill in your type
}
object Model {
implicit def kmeansModel(kmean: Kmeans): Model = new Model {
def setK() = kmeans.setK() // delegate to actual Kmeans
def fit() = kmeans.fit() // delegate to actual Kmeans
}
implicit def bisectingKmeansModel(): Model = ??? // similarly
// usage
val model: Model = if (modelName == "KMeans") {
new KMeans()
} else if (modelName == "BisectKMeans") {
new BisectingKMeans()
} else {
??? // other cases
}
model.setK()
model.fit()
In order to invoke methods .setK() and .fit(), the compiler has to "know" that the variable model is of a specific type that has those methods. You're trying to say, "the variable might be this type or it might be that type but they both have these methods so it's okay."
The compiler doesn't see it that way. It says, "if it might be A and it might be B then it must be the LUB (least upper bound), i.e. the nearest type they both inherit from."
Here's one way to achieve what you're after.
class KMeans { //parent type
def setK(): Unit = ???
def fit(): Unit = ???
}
class BisectingKMeans extends KMeans {
override def setK(): Unit = ???
override def fit(): Unit = ???
}
val model =
if (modelName == "KMeans")
new KMeans()
else //always end with "else", never "else if"
new BisectingKMeans()
model.setK()
model.fit()
I want to have a collection of objects, each object a companion of a different class, which classes all share a common method defined in a superclass that can be invoked when looping through the collection with a foreach(). I want the constructors of these sibling-classes to have the same named parameters and default parameter values as each other. Finally, I want to minimize repeated code.
Thus far, I am trying to do this with case classes, since--if it worked--it would eliminate all the duplicated code of the companion-objects for each type. The problem is that if I put all these companion objects into a Set, when I take them out again I lose the default parameters and parameter names.
Here is some example code of what I am describing:
trait MyType {
val param: String
def label = param // all instances of all subclasses have this method
}
case class caseOne(override val param: String = "default") extends MyType
case class caseTwo(override val param: String = "default") extends MyType
object Main extends App {
// I can construct instances using the companion objects' `apply()` method:
val works1 = caseOne(param = "I have been explicitly set").label
// I can construct instances that have the default parameter value
val works2 = caseOne().label
// But what I want to do is something like this:
val set = Set(caseOne, caseTwo)
for {
companion <- set
} {
val fail1 = companion() // Fails to compile--not enough arguments
val fail2 = companion(param = "not default") // Fails also as param has lost its name
val succeeds = companion("nameless param") // this works but not what I want
println(fail1.label + fail2.label) // this line is my goal
}
}
Notably if the Set has only one element, then it compiles, suggesting the inferred type of the multi-element Set lacks the parameter name--even though they are the same--and the default values. Also suggesting that if I gave the Set the right type parameter this could work. But what would that type be? Not MyType since that is the type of the companion classes rather that the objects in the Set.
I could define the companion objects explicitly, but that is the repeated code I want to avoid.
How can I loop through my collection, constructing instances of MyType subclasses on each iteration, with constructors that have my desired parameter names and default values? All while minimizing repeated code?
Update: Originally the example code showed caseOne and caseTwo as having different default values for param. That was incorrect; they are now the same.
You're not going to be able to get exactly what you want since you don't really have much control over the auto-generated companion objects. In particular for this to work they would all need to extend a common trait. This is why it fails to compile when the set has more than one companion object; even though they all have a method with the same signature, they don't extend a common trait for the compiler to utilize.
You can use a nested case class and get something very similar though:
trait MyType {
val param: String
def label = param // all instances of all subclasses have this method
}
abstract class MyTypeHelper(default: String) {
case class Case(param: String) extends MyType
def apply(param: String) : Case = Case(param)
def apply(): Case = apply(default)
}
object One extends MyTypeHelper("default one")
object Two extends MyTypeHelper("default two")
object Example {
val works1 = One(param = "I have been explicitly set").label
val works2 = One().label
val set = Set(One, Two)
for {
companion <- set
} {
val a = companion()
val b = companion(param = "not default")
val c = companion("nameless param")
println(a.label + b.label)
}
}
Instead of having a caseOne type, you have One.Case, but it still implements MyType so you shouldn't have any issue anywhere else in the code that uses that trait.
I've got the following code:
import com.github.nscala_time.time.Imports._
class Account {
def balance(date: DateTime): Double = {
/* some logic that calculates balance on given date */
val calculatedBalance = 42
calculatedBalance
}
def balance: Double = balance(DateTime.now)
}
class Deposit(val interestRate: Double) extends Account {
override def balance(date: DateTime): Double = {
/* some logic that calculates balance for deposit account */
val calculatedBalance = 100 * interestRate;
calculatedBalance
}
}
I try to use these classes in the following way:
val simpleAccount = new Account
val depositAccount = new Deposit(0.1)
val simpleBalanceOnDate = simpleAccount.balance(DateTime.now + 1.month) // A
val depositBalanceOnDate = depositAccount.balance(DateTime.now + 1.month) // B
val simpleBalance = simpleAccount.balance // C
val depositBalance = depositAccount.balance // D
Cases A, B and C are compiled without any errors, but for the line D I see error message:
Error:(28, 38) ambiguous reference to overloaded definition,
both method balance in class Deposit of type (date: com.github.nscala_time.time.Imports.DateTime)Double
and method balance in class Account of type => Double
match expected type ?
val depositBalance = depositAccount.balance
^
Can you please explain why there is a compilation error in case D and why there are no in case C?
Thanks in advance!
I suppose the compiler is confused about parameterless method inheritance, although I can't explain why honestly, for a quick solution this should work:
class Account {
{ ... }
def balance(): Double = balance(DateTime.now)
}
val depositAccount = new Deposit(0.1)
val depositBalance = depositAccount.balance()
Why this happens is obscure to me, maybe somebody else knows how the scala compiler is seeing parameterless method inheritance.
Also reading around, specifically Programming in Scala:
Such parameterless methods are quite common in Scala. By contrast, methods defined with empty parentheses, such as def height(): Int, are called empty-paren methods. The recommended convention is to use a parameterless method whenever there are no parameters and the method accesses mutable state only by reading fields of the containing object (in particular, it does not change mutable state).
This convention supports the uniform access principle,1 which says that client code should not be affected by a decision to implement an attribute as a field or method. For instance, we could have chosen to implement width and height as fields instead of methods, simply by changing the def in each definition to a val:
abstract class Element {
def contents: Array[String]
val height = contents.length
val width =
if (height == 0) 0 else contents(0).length
}
The two pairs of definitions are completely equivalent from a client's point of view. The only difference is that field accesses might be slightly faster than method invocations, because the field values are pre-computed when the class is initialized, instead of being computed on each method call. On the other hand, the fields require extra memory space in each Element object. So it depends on the usage profile of a class whether an attribute is better represented as a field or method, and that usage profile might change over time. The point is that clients of the Element class should not be affected when its internal implementation changes.
Why don't you provide a default argument like this:
class Account {
def balance(date: DateTime = DateTime.now): Double = {
/* some logic that calculates balance on given date */
val calculatedBalance = 42
calculatedBalance
}
}
class Deposit(val interestRate: Double) extends Account {
override def balance(date: DateTime): Double = {
/* some logic that calculates balance for deposit account */
val calculatedBalance = 100 * interestRate;
calculatedBalance
}
}
val simpleBalanceOnDate = simpleAccount.balance(1) // A
val depositBalanceOnDate = depositAccount.balance(1) // B
val simpleBalance = simpleAccount.balance() // C
val depositBalance = depositAccount.balance() // D
I have a case class representing my domain:
case class MyModel(rawValue: String, transformedValue: String)
rawValue maps to a value in the database and is properly parsed and bound. What I am trying to do is add transformedValue to my model: this value is just some arbitrary transformation that I perform on the rawValue. It does not map to any data in the database / query.
I have a parser (prior to adding transformedValue) that looks like this:
val parser = {
get[String]("rawValue") map {
case rawValue => MyModel(rawValue)
}
}
Since MyModel is immutible and I can't insert transformedValue into it after its been created, what and where is the best way to do and add this transformation (e.g. adding ad-hoc values to the Model) preferably without using vars?
Coming from Java, I would probably just have added a getTransformedValue getter to the domain class that performs this transformation on the rawValue attribute.
Since transformedValue seems to be a derived property, and not something that would be supplied in the constructor, you can define it as an attribute in the body of the function, possibly using the lazy qualifier so that it will only be computed on-demand (and just once for instance):
case class MyModel(rawValue: String) {
lazy val transformedValue: String = {
// Transformation logic, e.g.
rawValue.toLowerCase()
}
}
val is evaluated when defined; def is evaluated when called. A lazy val is evaluated when it is accessed the first time.
It may be appropriate to use lazy in the case of an expensive computation that is rarely needed, or when logic requires it. But for most cases a regular val should be used. Quoting:
lazy val is not free (or even cheap). Use it only if you absolutely need laziness for correctness, not for optimization.
I don't see why you wouldn't just do the transformation in the parser itself:
def transformation(rawValue: String): String = ...
val parser = {
get[String]("rawValue") map {
case rawValue => MyModel(rawValue, transformation(rawValue))
}
}
Or if you don't want to do it there for some reason, you can use copy to create a new copy of MyModel with a new value:
val model = MyModel("value", ..)
val modelWithTransform = model.copy(transformedValue = transformation(model.rawValue))
You could also overload apply to automatically apply the transformation within the companion object:
case class MyModel(rawValue: String, transformedValue: String)
object MyModel {
def apply(value: String): MyModel = MyModel(rawValue, transformation(rawValue))
val parser = {
get[String]("rawValue") map {
case rawValue => MyModel(rawValue)
}
}
}
MyModel may be immutable, but you can always create another copy of it with some values changed.
Turns out it was easier than I thought and the solution did look like what I said I would have done in java:
I just add a function to MyModel that does this transformation:
case class MyModel(rawValue: String) {
def transformedValue = {
// do the transformation here and return it
}
}
Search results so far have led me to believe this is impossible without either a non-primary constructor
class Foo { // NOT OK: 2 extra lines--doesn't leverage Scala's conciseness
private var _x = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
or sacrificing the name of the parameter in the primary constructor (making calls using named parameters ugly)
class Foo(private var _x: Int) { // OK: concise
def x = _x
}
val f = new Foo(_x = 123) // NOT OK: named parameter should be 'x' not '_x'
ideally, one could do something like this:
class Foo(private var x: Int) { // OK: concise
// make just the getter public
public x
}
val f = new Foo(x = 123) // OK: named parameter is 'x'
I know named parameters are a new thing in the Java world, so it's probably not that important to most, but coming from a language where named parameters are more popular (Python), this issue immediately pops up.
So my question is: is this possible? (probably not), and if not, why is such an (in my opinion) important use case left uncovered by the language design? By that, I mean that the code either has to sacrifice clean naming or concise definitions, which is a hallmark of Scala.
P.S. Consider the case where a public field needs suddenly to be made private, while keeping the getter public, in which case the developer has to change 1 line and add 3 lines to achieve the effect while keeping the interface identical:
class Foo(var x: Int) {} // no boilerplate
->
class Foo { // lots of boilerplate
private var _x: Int = 0
def this(x: Int) { this(); _x = x }
def x = _x
}
Whether this is indeed a design flaw is rather debatable. One would consider that complicating the syntax to allow this particular use case is not worthwhile.
Also, Scala is after all a predominantly functional language, so the presence of vars in your program should not be that frequent, again raising the question if this particular use case needs to be handled in a special way.
However, it seems that a simple solution to your problem would be to use an apply method in the companion object:
class Foo private(private var _x: Int) {
def x = _x
}
object Foo {
def apply(x: Int): Foo = new Foo(x)
}
Usage:
val f = Foo(x = 3)
println(f.x)
LATER EDIT:
Here is a solution similar to what you originally requested, but that changes the naming a bit:
class Foo(initialX: Int) {
private var _x = initialX
def x = _x
}
Usage:
val f = new Foo(initialX = 3)
The concept you are trying to express, which is an object whose state is mutable from within the object and yet immutable from the perspective of other objects ... that would probably be expressed as an Akka actor within the context of an actor system. Outside the context of an actor system, it would seem to be a Java conception of what it means to be an object, transplanted to Scala.
import akka.actor.Actor
class Foo(var x: Int) extends Actor {
import Foo._
def receive = {
case WhatIsX => sender ! x
}
}
object Foo {
object WhatIsX
}
Not sure about earlier versions, but In Scala 3 it can easily be implemented like follows:
// class with no argument constructor
class Foo {
// prive field
private var _x: Int = 0
// public getter
def x: Int = _x
// public setter
def x_=(newValue: Int): Unit =
_x = newValue
//auxiliary constructor
def this(value: Int) =
this()
_x = value
}
Note
Any definition within the primary constructor makes the definition public, unless you prepend it with private modifier
Append _= after a method name with Unit return type to make it a setter
Prepending a constructor parameter neither with val nor with var, makes it private
Then it follows:
val noArgFoo = Foo() // no argument case
println(noArgFoo.x) // the public getter prints 0
val withArgFoo = Foo(5) // with argument case
println(withArgFoo.x) // the public getter prints 5
noArgFoo.x = 100 // use the public setter to update x value
println(noArgFoo.x) // the public getter prints 100
withArgFoo.x = 1000 // use the public setter to update x value
println(withArgFoo.x) // the public getter prints 1000
This solution is exactly what you asked; in a principled way and without any ad hoc workaround e.g. using companion objects and the apply method.