I was looking at some Scala 2 code in a project I am working on that seemed very strange to me.
Suppose there is a method that takes a function as an argument like:-
def invoke(
request: Request,
block: (Request) => Future[Result]
)
The normal form of function literal that I am familiar with, would allow us to call invoke like this:
obj.invoke(
request,
(req: Request) => {
// a bunch of code
}
)
However, I am looking at some code where the sole argument is within the braces like:
obj.invoke(
request,
{
req: Request =>
// a bunch of code
}
)
Are the above two styles synonymous? If not then what is happening in the second way and when should it be used?
I am pretty new to Scala and have been reading from "Programming in Scala" but don't recall anything similar to the code I wrote above.
Related
I've got an akka-http application that uses akka-streams for data processing. So, it makes some sense to complete the request with Source[Result, _] to get backpressure across HTTP boundary for free.
Versions:
akka-http 10.0.7
akka-streams 2.5.2
akka 2.5.2
This is the simplified version of the code, and it works just fine.
pathEnd { post { entity(asSourceOf[Request]) { _ =>
complete {
Source.single("ok")
}
}}}
Since this enpoint is supposed to create and entity, instead of returning 200 OK to the requester I'd like to return 204 CREATED status code. However, I wasn't able to find a way to do that:
complete { Created -> source.single("ok") } fails compilation with Type mismatch, expected: ToResponseMarshallable, actual: (StatusCodes.Success, Source[String, NotUsed])
complete { source.single((Created, "ok")) } fails with Type mismatch, expected: ToResponseMarshallable, actual: Source[(StatusCodes.Success, String), NotUsed]
complete(Created) { Source.single("ok") } fails with Type mismatch, expected: RequestContext, actual: Source[String,NotUsed]
complete(Created, Source.signle("ok") fails with too many arguments for method complete(m: => ToResponseMarshallable)
It looks like custom marshaller might be a way to achieve that, but it'll basically mean I'll need one unmarshaller per endpoint, which isn't quite convenient or clear.
So, the question is, are there a (more convenient than custom unmarshaller) way to complete the request with Source[_,_] while also providing status code.
From the documentation:
complete(Created -> "bar")
If you want to provide some Source of data then construct the HttpResponse and pass it to complete:
import akka.http.scaladsl.model.HttpEntity.Chunked
import akka.http.scaladsl.model.ContentTypes
import akka.http.scaladsl.model.HttpEntity.ChunkStreamPart
complete {
val entity =
Chunked(ContentTypes.`text/plain(UTF-8)`,
Source.single("ok").map(ChunkStreamPart.apply))
HttpResponse(status = Created, entity=entity)
}
I hit this problem and took the approach of using mapResponse to override the status code. This is the simplest approach I've found.
mapResponse(_.copy(status = StatusCodes.Accepted)) {
complete {
Source.single("ok")
}
}
The drawback of Ramon's answer is that you become responsible for both marshalling the stream (to a ByteString), and for the content negotiation.
What is the most 'scala-ic' way to capture a value (possibly one that is not idempotent) for logging and returning the same value.
I can think of 'return' statement the only way to do it, but apparently using 'return' should be avoided in scala .
Use case:
def myfunc(argument) : ReturnType{
val response:ReturnType = dependency()
// dependency() is not idemptotent
// so calling more than once will have side-effects
logger.debug(response.member1 , response.member2)
return response
}
Is there a way to achieve this without using a 'return' keyword.
I am a newbie to scala so some (or most) of what I said could be wrong, and would be happy to be corrected.
Just reifying #Shadowlands answer.
def myfunc(argument: ArgType): ReturnType {
val response = dependency()
logger.debug(response.member1, response.member2)
response
}
I'm new rather new to Scala so I think this might be a very small problem.
I'm currently trying to change the method chat from using the deprecated WebSocket.async to WebSocket.tryAccept. The application uses the sample chat found at PlayFramework websocket-chat
I'm having trouble creating the complex Future type that the method requires.
This is the old method:
def chat() = WebSocket.async[JsValue] {
request =>
ChatRoom.join("User: 1")
}
New method:
def chat2() = WebSocket.tryAccept[JsValue] {
request =>
try {
// ChatRoom.join returns (iteratee,enumerator)
ChatRoom.join("User: 1").map(e => Right(e))
} catch {
case e: Exception =>
Left(Ok("Failed")) // Error here
}
}
My error message:
found : Left[Result,Nothing]
required: Future[Either[Result,(Iteratee[JsValue, _], Enumerator[JsValue])]]
I have no idea how I am supposed to create such a complex result for such a simple message.
Although ChatRoom.join("User: 1").map(e => Right(e)) doesn't show any errors now, I'm unsure if this is the correct implementation.
I'm not in front of an IDE at the moment, so I can't answer fully, but the return type it's asking for isn't as complex as it seems. An "Either" is a "Left" or a "Right" in the same way that an "Option" is a "Some" or a "None". So what it's asking for is a Future (which Websocket.async should also have required) that contains either a Left[Result] -- the fail-to-connect case, or a Right[(Iteratee, Enumerator)] -- the success case. Assuming that Chatroom.join returns a Future[(Iteratee, Enumerator)], the map operation is simply wrapping that in a "Right". The first thing I'd try is wrapping Left(Ok("Failed")) in a Future and see what happens.
In the Circumflex framework, you can map an URL to a block like this:
get("/foo") = {
"hello, world!"
}
which, when browsing to /foo, will show the given string as expected. Now, to write a complete web application, you almost always need some form of authentication and authorisation. I'm trying to write some kind of wrapper for the above construct, so I can write this:
get("/foo") = requireLogin {
"hello, world!"
}
The requireLogin method would then check if the user is logged in, and if yes, execute the given block. If not, however, it should do a redirect to the login page.
Now I somehow can't get the syntax right (i'm still a Scala newbie). How would you do this in a generic fashion?
Try something like this:
def executeMaybe[A](work: => A): Option[A] =
if (util.Random.nextBoolean)
Some(work)
else
None
This executes the passed code with probability 0.5, returning Some(<result delivered by work>), or returns None is the other cases. You can call it either like this:
val v = executeMaybe(42)
or with block notation:
val v = executeMaybe {
// do some work
// provide return value
}
The trick is to use a by-name parameter, signalled by the => symbol. Read more e.g. here: http://daily-scala.blogspot.com/2009/12/by-name-parameter-to-function.html
The way I asked it, Jean-Philippe's answer is correct.
But here's some information specific to Circumflex:
In the Circumflex RequestRouter, the following can be used to implement the required method:
def requireLogin (f: => RouteResponse ): RouteResponse = {
if(loggedIn) {
return f
}
else {
return sendRedirect("/login")
}
}
The reason behind this was getting clear with the hint from Jean-Philippe's answer, and once I remembered that the following call isn't an assignment of a block to some internal data, but is mapped to another method call instead.
So, the call
get("/") = {...}
is actually mapped to this:
get.update("/", {...})
The block is passed in as a By-Name parameter, so the return value of requireLogin must be the same - which, for Circumflex, is RouteResponse, and not a function.
You also can use j2ee container authentication with <login-config> and <security-constraint> stuff inside web.xml
I've been reading through the source code for Moq and I came across the following unit test:
Assert.Throws<ArgumentOutOfRangeException>(() => Times.AtLeast(0));
And for the life of me, I can't remember what () => actually does. I'm think it has something to do with anonymous methods or lambdas. And I'm sure I know what it does, I just can't remember at the moment....
And to make matters worse....google isn't being much help and neither is stackoverflow
Can someone give me a quick answer to a pretty noobish question?
Search StackOverflow for "lambda".
Specifically:
() => Console.WriteLine("Hi!");
That means "a method that takes no arguments and returns void, and when you call it, it writes the message to the console."
You can store it in an Action variable:
Action a = () => Console.WriteLine("Hi!");
And then you can call it:
a();
()=> is a nullary lambda expression. it represents an anonymous function that's passed to assert.Throws, and is called somewhere inside of that function.
void DoThisTwice(Action a) {
a();
a();
}
Action printHello = () => Console.Write("Hello ");
DoThisTwice(printHello);
// prints "Hello Hello "
It's a lambda expression. The most common syntax is using a parameter, so there are no parentheses needed around it:
n => Times.AtLeast(n)
If the number of parameters is something other than one, parentheses are needed:
(n, m) => Times.AtLeast(n + m)
When there are zero parameters, you get the somewhat awkward syntax with the parentheses around the empty parameter list:
() => Times.AtLeast(0)
() => Times.AtLeast(0)
() indicates that the lambda function has no parameters or return value.
=> indicates that a block of code is to follow.
Times.AtLeast(0) calls the Times class's static method AtLeast with a parameter of 0.
That's the definition of a lambda (anonymous) function. Essentially, it's a way to define a function inline, since Assert.Throws takes a function as an argument and attempts to run it (and then verify that it throws a certain exception).
Essentially, the snippet you have there is a unit test that makes sure Times.AtLeast(0) throws a ArgumentOutOfRangeException. The lambda function is necessary (instead of just trying to call the Times.AtLeast function directly from Assert.Throws) in order to pass the proper argument for the test - in this case 0.
MSDN KB article on the topic here: http://msdn.microsoft.com/en-us/library/bb882516.aspx
I don't program in C#, but Googling "C# Lambda" provided this link that answers your question!!!