How do I declare the signature of a function that must return one of its arguments? (in any language*) - scala

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.

Related

Assign values of a tuple to single variables in Scala

is there a nice possibilyt to assign the values of a tuple to single variables? Here is what i want to do but it throws an error:
var a : Int = _
var b : Int = _
def init() {
(a,b) = getTuple() // returns (Int, Int)
}
def someFunction = {
// use a here
}
def someOtherFunction = {
// use b here
}
Error: ';' expected but '=' found.
(a, b) = getTuple()
Do i really have to do this ._1 and ._2 thing?
val tuple = getTuple() // returns (Int, Int)
a = tuple._1
b = tuple._2
Thanks for answering.
As you can see in Section 6.15 Assignments of the Scala Language Specification, the lefthand-side of an assignment expression must be either a bare identifier:
foo = ???
// either an assignment to a local mutable `var` or syntactic sugar for:
foo_=(???)
a member access:
foo.bar = ???
// syntactic sugar for:
foo.bar_=(???)
or a method call:
foo(bar) = ???
// syntactic sugar for:
foo.update(bar, ???)
Pattern Matching is only available for value definitions (see Section 4.1 Value Declarations and Definitions) and variable definitions (see Section 4.2 Variable Declarations and Definitions).
So, both of the following would be legal:
var (a, b) = getTuple()
val (a, b) = getTuple()
By the way, there are a number of highly non-idiomatic things in your code:
It is highly unusual to pass an empty argument list to a method call. Normally, methods that have no parameters should have no parameter lists instead of an empty parameter list. The only exception are methods that have side-effects, where the empty parameter list serves as kind of a "warning flag", but methods which have side-effects are highly non-idiomatic as well. So, getTuple should be defined and called like this:
def getTuple = ???
getTuple
instead of
def getTuple() = ???
getTuple()
On the other hand, if the method does have side-effects, it shouldn't be called getTuple because that implies that the method "gets" something, and there is no indication that it also changes something.
In Scala, getters and setters are not called getFoo and setFoo but rather foo and foo_=, so the method should rather be called tuple.
Mutable variables are highly non-idiomatic as well, they should probably rather be vals.
Tuple destructuring is an opaque call to unapply method of TupleN[T1, ..., Tn] companion object, aka extractor object.
As the documentation suggests, one can only have a variable initialization with an extractor object, but not assignment.
So, the only possible way is to use it like this:
def getTuple = (1,2)
def main() = {
val (a,b) = getTuple
// use a,b
}
The fact that you use a var may be the sign you have a design flaw. Try to refactor your code or specify the exact problem you're trying to solve with the var to justify its usage (although what you're trying to do with extractor is still impossible)

Basic Scala: Methods holding parameters?

I am reading the book Programming in Scala and in chapter 10 I had to write:
abstract class Element {
def contents: Array[String]
def height: Int = contents.length
def width: Int = if (height == 0) 0 else contents(0).length
}
class ArrayElement(conts: Array[String]) extends Element {
def contents: Array[String] = conts
}
but the concept I don't catch here is how can I define a method that is holding a variable? As far as I know, methods return a value, it can be a computed value or an instance variable directly, but they can't hold a value. Am I forgetting a basic concept about the programming language that applies here too?
Try this out:
abstract class Foo { def bar: Int }
class Baz(val bar: Int) extends Foo
In Scala, you can implement methods by creating member variables with same name and same type. The compiler then adds a corresponding getter-method automatically.
The member variable and the getter-method are still two different things, but you don't see much difference syntactically: when you try to access it, its both just foo.bar, regardless of whether bar is a method or a member variable.
In your case
def contents: Array[String] = conts
is just an ordinary method that returns an array, an equivalent way to write the same thing would be
def contents: Array[String] = {
return conts
}
Since the array is mutable, you can in principle use this method to modify entries of your array, but the method itself is really just a normal method, it doesn't "hold" anything, it just returns reference to your array.
Edit: I've just noticed that conts is actually not a member variable. However, its still captured in the definition of the contents method by the closure-mechanism.

How to access to the parameter of the higher order function in scala

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.

Scala anonymous class type mismatch

I am creating a list holding Comparable objects and wish to create one object that serves as the minimum of the list, such that it always returns -1 for its compareTo method. Other methods in the list, like print here requires an input of type A. If I compile the code I get the following error:
error: type mismatch;
found : java.lang.Object with java.lang.Comparable[String]
required: String
l.print(l.min)
Anyone have any idea about how can a create such a minimum element so that it is always smaller than any other elements in the list?
class MyList[A <: Comparable[A]] {
val min = new Comparable[A] {
def compareTo(other: A) = -1
}
def print(a: A) = {
println(a)
}
}
class Run extends Application {
val l = new MyList[String]
l.print(l.min)
}
Well, the input passed is not equal to the input provided, right? print needs an A:
def print(a: A) = {
And min does not return an A:
val min = new Comparable[A] {
As to creating such an A as you want it... how could you possibly go about it? You don't know anything about A -- you don't know what its toString returns, you don't know what methods it implements, etc.
So, basically, change your algorithm.
You are getting a compile error because you're trying to use a Comparable where the compiler is expecting a A, what you really want to do is:
val min: A = new A {
def compareTo(other: A) = -1
}
but you can't do this in Scala (or Java), because you're trying to create an object of an unknown type (A). You could do this using reflection, but you would still have the problem of creating an object which was less than any other object in the list.
Also, be aware that your implementation of compareTo will have problems with almost any sorting algorithm you choose, because you can't guarantee compareTo is always called from min. For example, you could get:
min.compareTo(list(0)) // returns -1
list(0).compareTo(min) // could be anything really
If you want a list that returns a specific object as the 'minimum' then you could just prepend a specific value to the sorted list:
class MyList2[A <: Comparable[A]] {
val min: A; // somehow create an instance of the class A
val list: List[A]
def sort(fn: (A, A) => Boolean) = {
min :: list.sort(fn)
}
}
but as Daniel says, this is probably the wrong way to go about it.

Can Scala allow free Type Parameters in arguments (are Scala Type Parameters first class citizens?)?

I have some Scala code that does something nifty with two different versions of a type-parameterized function. I have simplified this down a lot from my application but in the end my code full of calls of the form w(f[Int],f[Double]) where w() is my magic method. I would love to have a more magic method like z(f) = w(f[Int],f[Double]) - but I can't get any syntax like z(f[Z]:Z->Z) to work as it looks (to me) like function arguments can not have their own type parameters. Here is the problem as a Scala code snippet.
Any ideas? A macro could do it, but I don't think those are part of Scala.
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// want something like this: def z[Z](f[Z]:Z=>Z) = w(f[Int],f[Double])
// a type parameterized function that takes a single type-parameterized function as an
// argument and then speicalizes the the argument-function to two different types,
// i.e. a single-argument version of w() (or wrapper)
}
}
You can do it like this:
trait Forall {
def f[Z] : Z=>Z
}
def z(u : Forall) = w(u.f[Int], u.f[Double])
Or using structural types:
def z(u : {def f[Z] : Z=>Z}) = w(u.f[Int], u.f[Double])
But this will be slower than the first version, since it uses reflection.
EDIT: This is how you use the second version:
scala> object f1 {def f[Z] : Z=>Z = x => x}
defined module f1
scala> def z(u : {def f[Z] : Z=>Z}) = (u.f[Int](0), u.f[Double](0.0))
z: (AnyRef{def f[Z]: (Z) => Z})(Int, Double)
scala> z(f1)
res0: (Int, Double) = (0,0.0)
For the first version add f1 extends Forall or simply
scala> z(new Forall{def f[Z] : Z=>Z = x => x})
If you're curious, what you're talking about here is called "rank-k polymorphism." See wikipedia. In your case, k = 2. Some translating:
When you write
f[X](x : X) : X = ...
then you're saying that f has type "forall X.X -> X"
What you want for z is type "(forall Z.Z -> Z) -> Unit". That extra pair of parenthesis is a big difference. In terms of the wikipedia article it puts the forall qualifier before 2 arrows instead of just 1. The type variable can't be instantiated just once and carried through, it potentially has to be instantiated to many different types. (Here "instantiation" doesn't mean object construction, it means assigning a type to a type variable for type checking).
As alexy_r's answer shows this is encodable in Scala using objects rather than straight function types, essentially using classes/traits as the parens. Although he seems to have left you hanging a bit in terms of plugging it into your original code, so here it is:
// this is your code
object TypeExample {
def main(args: Array[String]):Unit = {
def f[X](x:X):X = x // parameterize fn
def v(f:Int=>Int):Unit = { } // function that operates on an Int to Int function
v(f) // applied, types correct
v(f[Int]) // appplied, types correct
def w[Z](f:Z=>Z,g:Double=>Double):Unit = {} // function that operates on two functions
w(f[Int],f[Double]) // works
// This is new code
trait ForAll {
def g[X](x : X) : X
}
def z(forall : ForAll) = w(forall.g[Int], forall.g[Double])
z(new ForAll{def g[X](x : X) = f(x)})
}
}
I don't think what you want to do is possible.
Edit:
My previous version was flawed. This does work:
scala> def z(f: Int => Int, g: Double => Double) = w(f, g)
z: (f: (Int) => Int,g: (Double) => Double)Unit
scala> z(f, f)
But, of course, it is pretty much what you have.
I do not think it is even possible for it to work, because type parameters exist only at compile-time. At run time there is no such thing. So it doesn't make even sense to me to pass a parameterized function, instead of a function with the type parameters inferred by Scala.
And, no, Scala has no macro system.