I found this foreach(_ => ()) in a code that uses Monix stream, I am not understanding the meaning. Can someone explain me this?
monix_concurrent_subject.foreach(_ => ())
As urmaul explained in the comments, it depends:
If the datastructure is eager, it does nothing. Examples are List, Option etc.
If the datastructure is lazy, it initialises its content. An example is a Stream.
Also as foreach returns nothing, it implies that somewhere will be a Side-Effect in the code before the foreach.
If you check the API (ConcurrentSubject.html#foreach) it states:
foreachL(cb: (O) ⇒ Unit): Task[Unit]
Creates a new Task that will consume the source observable, executing the given callback for each element.
() represents the value in the type of Unit. It is perhaps unusual-looking but it is a true value nevertheless, akin to how 42 represents a value in the type of Int. For example, we can write
val u: Unit = ()
similarly to
val i: Int = 42
() does not carry much meaning beyond indicating some side-effect occurred in a function.
Now consider the following function of type Int => Unit
(x: Int) => ()
Note how we do nothing with parameter x on the right of =>, that is, it is not used at all. We can express this meaning explicitly using an underscore _
(_: Int) => ()
or even simply
_ => ()
if type inference can figure out the types. Applying an argument to this function
((x: Int) => ())(42)
results in nothing interesting. So putting these pieces together we get perhaps the following interpretation of meaning of _ => ():
do nothing effect
trivial effect
no operation effect
effect without effect
However despite _ => () having no direct effect it may have some indirect effect when passed to foreach as explained by pme.
Regarding
monix_concurrent_subject.foreach(_ => ())
it seems to me here foreach(_ => ()) is more of a hack to achieve something for which monix_concurrent_subject should really provide a proper method.
Related
I have a method which returns Future[Unit], so when I call whenReady
These two options work: whenReady(doItAsync())(_ => {}) and whenReady(doItAsync()) { _ => }
but this doesn't: whenReady(doItAsync())(() => {})
Are not _ of type Unit and empty params list equivalent in this case?
Although type Unit is similar to void from other languages it is not exactly the same.
This particular trouble comes from a limitation in Java (and thus Scala) generics implementation: they are implemented using type erasure. Particularly it means that generic method can't change the number of arguments. Now what happens when type parameter is Unit? We still must have the same number of arguments and also can't magically change return type to return nothing (void) because this will be a different signature. So the answer is to use some fake type with only fakes values: scala.runtime.BoxedUnit. And thus Unit might represent actual parameter that you don't need but has to be there. And so type signature () => {} doesn't match that because it takes no parameters.
Note also that in Java itself there is the same issue and thus there is a similar thing called java.lang.Void
Update:
To make the point more clear consider following generic vs. non-generic code:
def foo(f: () => String) = println(f())
def fooGeneric[T](arg: T, f: (T) => String) = println(f(arg))
foo(() => "Non-generic")
fooGeneric[Unit]((), (_) => "generic")
Note that also logically fooGeneric[Unit] is the same as foo, you still have to pass first argument and pass function that accept an (useless) argument as the second parameter.
Are not _ of type Unit and empty params list equivalent in this case?
No. _ => {} defines a function with single parameter (which happens in this context to have type Unit), () => {} defines a function with no parameters. Their types are Unit => Unit and () => Unit, or without syntactic sugar Function1[Unit, Unit] and Function0[Unit]. These types aren't actually related: neither of them is a subtype of the other.
You can write a single-argument anonymous function taking Unit with () using pattern-matching: { case () => ... }. But there is no point to doing that.
In this comment, #Ben suggested that call by name is equivalent to call by value where values are zero-argument functions. If I understood correctly,
def callByName(x: => Int) = {
// some code
}
callByName(something())
is equivalent to
def callByValue(x: () => Int) = {
// same code as above, but all occurrences of x replaced with x()
}
callByValue(()=>something())
(Edit: I fixed mistake in signature as pointed out by #MichaelZajac, #LukaJacobowitz: originally, it said callByValue(x: Int).)
In other words, the whole "call by name" concept is just syntactic sugar: everything it does can be achieved (with a few extra keystrokes) using "call by value". If true, it makes it very easy to understand call by name; in fact, I've used this technique in python (python has first-class functions).
However, further down in the comments, the discussion became somewhat more confusing, and I was left with the feeling that it's not quite so simple.
So is there something more substantive to "call by name"? Or is it just an automatic creation of zero-argument functions by the compiler?
I'm assuming you meant your callByValue function to take a () => Int instead of just an Int as otherwise it wouldn't make a lot of sense.
It's pretty much exactly what you think. The compiler generates a Function0 instance. You can see this pretty nicely when you decompile Scala code with Javap.
Another thing of note is, that the generated Function0 will be reevaluated every time you use the by-name parameter inside your function, so if you only want it to be computed once you'll want to do something like this:
def callByName(x: => Int) = {
val a = x
// do something with a here
}
Here is some more information on the whole concept.
Also you can see how Scala compiles by-name parameters quite neatly in this question:
def getX[T <: X](constr: ⇒ T): Unit = {
constr
}
decompiled in Java is equivalent to:
public <T extends X> void getX(Function0<T> constr) {
constr.apply();
}
Yes, but your example isn't quite right. The signature of callByValue, as written in your question, will evaluate x before callByValue is invoked.
The following would be roughly equivalent to a call-by-name:
def callByValue(x: () => Int) = {
// same code as above, but all occurrences of x replaced with x()
}
The distinction is important, because your version of callByValue would only accept Ints, not functions that return Ints. It also wouldn't compile if you followed the procedure of replacing x with x().
But yes, a call-by-name parameter of => A is roughly equivalent to () => A, except that the former is simply more convenient to use. I say roughly because they are different types, and their applications are slightly different. You can specify () => A to be the type of something, but not => A. And of course with x: () => A, you must manually call x() instead of x.
Sorry for the nebulous title, I had a hard time to to formulate what I mean. For that reason, lets directly dive into the code:
def bar(b: Int => String) = b(23)
def foo(b: => String) = bar(_ => b)
foo("foo" + "bar")
I found a similar code in the play framework and was wondering what actually happens with that code. I tinkered a bit and figured that bar(_ => b) will just create a function1 with the required argument type (given by bars signature) and uses the given function0 to generate the return value, ignoring the actual parameter of the function1.
However, this is just me trying to figure out what happens, a more definitive answer would be way better for my understanding - and besides that I might be completely wrong.
You're sort of right, except that => String is not a Function0 - () => String is.
=> String is a call-by-name string. It'll be evaluated when it's referred to.
def foo(b: String) = bar(_ => b) would also get the job done, with the exception that b would be evaluated eagerly.
def foo(user, id): Future[Option[Bar]] =
bar(user, id).map(_.map(_.address.flatMap(_.street)))
.flatMap {
case Some(street) =>
baz(user, street).flatMap(_ => get(id))
case None => successful(None)
}
Function bar returns an Option[UserInfo], which I then map to a UserInfo. Address is also an Option so I flatMap that to have access to street. Then simply if there exists a street I want to call baz, if not then None. Ignore the business logic, it's made up for the example.
There's a problem with the code here as it won't compile.
Some(street) is an Option, since the flatMap on line 3 is being called on the result of the mapping on the first _, instead of _.address.
Whilst I could get this to work with some parenthesis juggling and so on, this code is starting to get hard to read and reason about.
Are for-comprehensions the answer?
P.S: There might be some type-information missing in this example so please ask and I will elaborate.
EDIT:
case class UserInfo(id: UserId, address: Option[Address])
case class Address(street: Option[List[Street]], state: Option[State])
If I understood method signatures right:
def bar(user, id): Option[UserInfo]
def baz(user, List[Street]): Future[BarId]
def get(id): Option[Bar]
You can implement your method something like this:
val streetsOpt: Option[List[Street]] = bar(user, id).flatMap(_.flatMap(_.address.flatMap(_.street)))
streetsOpt.flatMap(streets => {
baz(user, streets).map(_ => get(id))
}).getOrElse(successful(None)))
Just quickly looking at this, within this line:
baz(user, street).flatMap(_ => get(id))
I don't think that the last flatMap won't work properly because you seem to be passing in a function which is of a type something like:
f: => A
i.e. extracting the underlying value from some context, whereas flatMap expects you to unpack this value and then wrap in a new context, and so has type:
f: A => M[B]
When you are making the call to
get(id)
Shouldn't this be being applied to a map method instead, which expects a function of type:
f: A => B
There are a couple of ways of dealing with nested contexts like this. I gave a talk about three that I know: monad transformers (explicit, more "standard", but a bit more verbose), Kleisli (very elegant, if you're willing to write in pointfree style), or my scalaz-transfigure library (a bit immature, a bit less explicit, but very concise).
I think I still have not fully understood what type () represent during function definition. So I can't come up concrete example of each case: () => Int; Unit=> Int.
Can someone give me an easy example of function literal with type () => Int and type Unit=>Int respectively? After that, I think I can learn what () is exactly is.
Thanks
*EDIT: * destin says they are same. But the following test seems to indicate otherwise: () can't be used in place expecting Unit.
scala> def inCase[A] ( b :Boolean, ifTrue : Unit => A, ifFalse : Unit => A ) : A =
| b match {
| case True => ifTrue()
| case _ => ifFalse()
| }
inCase: [A](b: Boolean, ifTrue: Unit => A, ifFalse: Unit => A)A
scala> inCase( True, () => 1, () => -1 )
<console>:11: error: type mismatch;
found : () => Int
required: Unit => ?
inCase( True, () => 1, () => -1 )
() in a function type is not a type at all, nor is it a value. () => is simply syntax to indicate a function that takes zero arguments. See the BNF notation in section 3.2.9 of the Scala specification.
When you see (Type1, Type2, Type3) => Type4, the () surrounds all of the argument types that the function takes. (Type1, Type2, Type3) is not a tuple type here -- the parentheses are just syntax. So when you see () => Type4, you have an argument list that takes zero parameters. Single argument functions are special, in that you can omit the parentheses.
Functions with no arguments, specified without the (), simply => Type4 are by-name parameters (which look like values, but are implemented as functions that get called implicitly when you try to evaluate their value.) They're defined in section 4.6.1 of the spec.
Parentheses can mean a bunch of other things in other contexts.
Parentheses in a function type declaration anywhere other than right before the => indicate a tuple type, and these can't be empty. (Section 3.2.5)
Empty parentheses () are the return value of functions whose return type is Unit. (Section 12.2.3) This actually becomes a real value in certain contexts, for example println(println("foo")) will print
foo <--- the argument to the inner println
() <--- the argument to the outer println
Parentheses are also syntax for function arguments when you make a function call, something that you're probably already aware of. These can be empty. They're defined in section 6.6 of the spec.
Parentheses are also syntax for function arguments when you define a method using def. These are described in section 4.6 of the spec.
Parentheses are also the syntax for creating tuple values (Section 6.9). If they're not empty, you get a TupleN where N is the number of values inside of the parentheses. If they are empty, the type of this expression is Unit. (Sections 6.9, 12.2.3)
I changed your example, to have both notations (and to use the more popular Boolean):
def inCase[A] (b:Boolean, ifTrue: ()=> A, ifFalse: Unit => A): A = b match {
case true => ifTrue ()
case _ => ifFalse ()
}
inCase (true, () => 1, (Unit) => -1)
Then I have to use the same notation on the calling site.
() is the only instance of the type Unit.
So () => Int as signature of a partial function means: takes the Unit object, does something and gives an Int.
Unit => Int means: takes any Unit object, does something and gives an Int.
Edit
"Scala’s Unit type roughly corresponds to void in Java; it is used whenever a function does not return an interesting result. In fact, because Scala is an expressionoriented language, every function returns some result. If no explicit return expression is given, the value (), which is pronounced “unit”, is assumed. This value is
of type Unit. Unit-returning functions are also called procedures. Here’s a more
“expression-oriented” formulation of the swap function in the first implementation
of quicksort, which makes this explicit:
def swap(i: Int, j: Int): Unit = {
val t = xs(i); xs(i) = xs(j); xs(j) = t
()
}
The result value of this function is simply its last expression – a return keyword is
not necessary. Note that functions returning an explicit value always need an “=”
before their body or defining expression."
Source: Programming in Scala - Martin Odersky (Page 14)