Since the following are equivalent:
-2
2.unary_-
and since parentheses are optional for methods with no arguments, shouldn't
2.unary_-()
also evaluate to -2 ? Instead, I get:
error: Int does not take parameters
The book I'm working through says that unary_- is a method, though this error seems to suggest it is a property of Int. Is this correct?
Proceeding from evan058's advice, I decided to run an experiement:
class Myint1(n:Int) {
def unary_-() = -n /* method definition has parentheses */
}
class Myint2(n: Int) {
def unary_- = -n /* no parentheses in definition */
}
val n1 = new Myint1(3)
val n2 = new Myint2(3)
n1.unary_- /* prints -3 */
n2.unary_- /* also gives -3 */
n1.unary_-() /* prints -3 */
n2.unary_-() /* throws error: Int does not take parameters */
So unary_- is a method, not a property. The reason for the behavior is that there is a difference between a method definition with parentheses and without. Note that, expectedly, -n1 and -n2 both result in -3.
Related
Can we have type variables in JSDoc?
For example I want to define identity function:
/**
* #param {a} x
* #return {a}
*/
const id = x => x;
But when I use it with concrete types id(2), editor always complains that type number is not assignable to type a. I understand why, as in Haskell or other similar languages the lower cased names in annotation is treat as type variable, but JS views it as concert type.
So is there a way to define type variables in JSDoc?
PS: Yea, I know that there is TS and Flow, and I should use them in stead of playing with annotations, but the project I'm working on now is not ready to be migrated to TS, but in same time I want to make things as safe as possible using JS only.
I think you're asking for a type definition for a method where the #param type is always the same as the #return type?
Borrowing from the Closure Compiler's Wiki: Declaring a bounded generic type:
/**
* #param {A} x
* #template A
* #return {A}
*/
const id = (x) => x;
/** #type {string} */
let str='';
/** #type {number} */
let num=1;
str=id(true); // Type warning.
str=id('string'); // Type safe.
str=id(1234); // Type warning.
num=id(true); // Type warning.
num=id('string'); // Type warning.
num=id(1234); // Type safe.
Produces the following warnings:
JSC_TYPE_MISMATCH: assignment
found : boolean
required: string at line 16 character 0
str=id(true)
^
JSC_TYPE_MISMATCH: assignment
found : number
required: string at line 20 character 0
str=id(1234)
^
JSC_TYPE_MISMATCH: assignment
found : boolean
required: number at line 22 character 0
num=id(true)
^
JSC_TYPE_MISMATCH: assignment
found : string
required: number at line 24 character 0
num=id('string')
How does one express the signature for a function that must return an argument (or this) that it receives (is called on), in TypeScript? Is there a programming language where this is possible?*
// In TypeScript (or consider it pseudo-code)
class C {
// EXAMPLE 1 – Not polymorphic
chainable(x): this // MUST not only return some C,
{} // but the same instance it was called on
}
// EXAMPLE 2
function mutate<T>(a: T[], x): T[] // MUST return a, not a new Array
{
/* So that this doesn't compile */ return Array.from(a);
/* But this is OK */ return a;
}
Conversely, how about a function that must return a new instance?
// EXAMPLE 3
function slice<T>(a: T[], x, y): T[] // MUST return a new Array
❌TypeScript
Go 2?
Would the following contract achieve the above?
contract referentiallyIdentical(f F, p P) {
f(p) == p
v := *p
}
type returnsSameIntSlice(type T, *[]int referentiallyIdentical) T
func main() {
var mutate returnsSameIntSlice = func(a *[]int) *[]int {
b := []int{2}
/* Would this compile? */ return &b
/* This should */ return a
}
}
C++20?
Could the above be expressed as a C++ concept?
✅Scala
*Originally, the question was about doing this in TypeScript, but since that isn't possible, I am curious if it is in another language.
Feel free to remove a tag if that language's type system can't express this
You can - in Scala.
Class with a method returning this.type:
class C {
var x = 0
/** Sets `x` to new value `i`, returns the same instance. */
def with_x(i: Int): this.type = {
x = i
this // must be `this`, can't be arbitrary `C`
}
}
In-place sort that guarantees to return exactly the same array (doesn't really sort anything here):
def sortInPlace[A: Ordered](arr: Array[A]): arr.type = {
/* do fancy stuff with indices etc. */
arr
}
If you attempt to return a different array,
def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3) // won't compile
you'll get an error at compile time:
error: type mismatch;
found : Array[Int]
required: arr.type
def badSortInPlace(arr: Array[Int]): arr.type = Array(1, 2, 3)
^
This is called a singleton type, and is explained in the spec.
In a language with parametric polymorphism, any function of the type
a → a
must be the identity function: since the function is polymorphic in a, it cannot possibly know anything about a, in particular, it cannot possibly know how to construct an a. Since it also doesn't take a world value or an IO monad or something equivalent, it cannot get a value from global state, a database, the network, storage, or the terminal. It also cannot drop the value, since it must return an a.
Ergo, the only thing it can do is to return the a that was passed in.
I have a function like so
def runOnce(request: Request): Future[Result] = {
}
When I call this runOnce function, if it has not been run, I want it to run some method and return that result. If it has been run, I just want it to return the original result (the request coming in will be the same).
I can do it if I have no param like so
lazy val hydratedModel = hydrateImpl(request)
future for efficient filtering
def fetchHydratedModel(): Future[HydratedModelRequest] = {
hydratedModel
}
How to do in first case?
There's a general solution to this problem, which is function memoization; for a pure function (one that has no side-effects - it will not work for non-pure functions), the result of a function call should always be the same for the same set of argument values. Therefore, an optimization is to cache the value on the first call and to return it for subsequent calls.
You can achieve this with something like the following (a memoization class for pure functions with a single argument, updated—see comment below—to make it thread-safe):
/** Memoize a pure function `f(A): R`
*
* #constructor Create a new memoized function.
* #tparam A Type of argument passed to function.
* #tparam R Type of result received from function.
* #param f Pure function to be memoized.
*/
final class Memoize1[A, R](f: A => R) extends (A => R) {
// Cached function call results.
private val result = scala.collection.mutable.Map.empty[A, R]
/** Call memoized function.
*
* If the function has not been called with the specified argument value, then the
* function is called and the result cached; otherwise the previously cached
* result is returned.
*
* #param a Argument value to be passed to `f`.
* #return Result of `f(a)`.
*/
def apply(a: A) = synchronized(result.getOrElseUpdate(a, f(a)))
}
/** Memoization companion */
object Memoize1 {
/** Memoize a specific function.
*
* #tparam A Type of argument passed to function.
* #tparam R Type of result received from function.
* #param f Pure function to be memoized.
*/
def apply[A, R](f: A => R) = new Memoize1(f)
}
Assuming that the function you're memoizing is hydrateImpl, you can then define and use runOnce as follows (note that it becomes a val not a def):
val runOnce = Memoize1(hydrateImpl)
runOnce(someRequest) // Executed on first call with new someRequest value, cached result subsequently.
UPDATE: Regarding thread-safety.
In reply to the comment from user1913596, the answer is "no"; scala.collection.mutable.Map.getOrElseUpdate is not thread-safe. However, it's fairly trivial to synchronize access, and I have updated the original code accordingly (embedding the call within sychronized(...)).
The performance hit of locking access should be negated by the improved execution time (assuming that f is nontrivial).
There are likely better ways to do this depending on your setup, but a simple solution is to do the following
private var model: Option[Future[HydratedModelRequest]] = None
def runOnce(request: Request): Future[Request] = {
if (model.isEmpty) {
model = hydrateImpl(request)
}
model.get
}
If the request is indeed the same for each call, another option would be to require the request implicitly and hydrate lazily.
implicit val request: Request
lazy val hydratedRequest: Future[HydratedModelRequest] = hydrateImpl(request)
I am really new to Scala and trying to study it.
I don't know how to access or using the parameter of higher order function. For example:
def higherOrderFunc(f: Int => Boolean): String = {
/* Logic to print parameter is here */
"Hello"
}
val func = higherOrderFunc(x => x > 1)
How can I print the value of x before I return value "Hello"
You can't. The argument does not exist in this context; it'd need to be passed into the higher-order function along with the anonymous function.
My understanding is Unit = void, but why I can pass in multiple argument?
So can anyone explain why the following code is valid?
def foo(x: Unit) = println("foo")
foo("ss", 1)
If you run your snippet with scala -print you'll roughly get the following output for the code:
/* Definition of foo */
private def foo(x: scala.runtime.BoxedUnit): Unit = {
/* Invocation of foo */
foo({
new Tuple2("ss", scala.Int.box(1));
scala.runtime.BoxedUnit.UNIT
});
As you can see, the arguments to foo are rewritten into a code block that creates a tuple but then returns UNIT.
I can't see a good reason for this behaviour and I'd rather get a compiler error thrown instead.
A related question which gives a decent answer to this is here:
Scala: Why can I convert Int to Unit?
From Section 6.26.1 of the Scala Language Specification v2.9, "Value Discarding":
If e has some value type and the expected type is Unit, e is converted to the expected type by embedding it in the term { e; () }.
So, in your case it seems ("ss", 1) is being converted to a tuple so that it can be treated as a single argument, then as that argument type is not Unit, it is converted to a block which computes that tuple value then returns unit to match with the required type of the parameter.