Is it possible to use reduce in a callback function? - reason

I have this simple component
let component = ReasonReact.statelessComponent("Input");
let make = (~name, ~onChange, ~value, _children) => {
...component,
render: (_self) =>
<input
name=name
onChange={(_) => {
onChange(name, "change")
}}
value=value />
};
and I'm trying to use it like this
<Input
name="
placeholder="Your email"
onChange={self.reduce((name, value) => Change(name, value))}
label=""
value={self.state.email} />
But I get this error on the onChange line
This is:
ReasonReact.Callback.t(string) (defined as (string) => unit)
But somewhere wanted:
(string, string) => unit
The incompatible parts:
unit
vs
(string) => unit
I think I understand the error, but I have no idea to to fix it. I also to define onChange like this
onChange={(name, value) => self.reduce((_, _) => Change(name, value))}
but this time I get
This is:
ReasonReact.Callback.t('a) (defined as ('a) => unit)
But somewhere wanted:
unit
Do you have an idea how to fix it ? Is it possible to call reduce inside another callback function ?

reduce takes a 1-ary function and returns a 1-ary function, but your onChange is expected to be a 2-ary function. Since you seem to control both sides of this, the simplest fix is to just use a tuple:
Definition:
onChange={self.reduce(((name, value)) => Change(name, value))}
Application:
onChange={(_) => {
onChange((name, "change"))
}}
Alternatively, if you don't control how the callback is used, you can wrap it in another function like you tried to, but since reduce returns a function you have to explicitly call it:
onChange={(name, value) => self.reduce(() => Change(name, value))()}
Note: The argument you pass to the callback returned by reduce is the same argument that will be passed to the callback passed to reduce, in this case just (). But value => self.reduce(val => Action(val))(value) is therefore equivalent to just doing self.reduce(val => Action(val)).

Related

Is it possible to call a generically-typed function by passing in a class specified in a map?

Asking here because I'm pulling out my hair trying to figure out what exactly it is I need to do here.
I'm writing a batch-processing endpoint that attempts to convert the body of a request to a specific Scala case class before executing the logic within the endpoint itself.
This is as far as I currently got. First, I have a function executeWithType that takes a generic type, a controller method, and the request body and executes the controller method after converting the request body to the provided type. The request param is available in a scope outside this function.
def executeWithType[A](action: () => Action[A], batchRequest: BatchRequest): Future[Result] = {
action()(request.map(_ => batchRequest.body.map(_.as[A]).get))
}
Then, I have some code that checks what endpoint to call and what type to cast to depending on what's in the BatchRequest itself.
val res: Future[Result] = (batchRequest.method, batchRequest.endpoint) match {
case ("POST", "/endpoint1") => {
executeWithType[EndpointOneType](controller.endpointOne _, batchRequest)
}
case ("POST", "/endpoint2") => {
executeWithType[EndpointTwoType](controller.endpointTwo _, batchRequest)
}
case _ => Future.successful(NotFound)
}
The above works perfectly fine - however, I want to avoid this sort of tuple-matching with individual cases if possible, and specify a Map that does this instead. In my ideal world, the end result of the code block immediately above would look like this:
val actions = Map(
Seq("POST", "/endpoint1") -> (controller.endpointOne _, EndpointOneType),
Seq("POST", "/endpoint2") -> (controller.endpointTwo _, EndpointTwoType)
)
val res = actions.get(Seq(batchRequest.method, batchRequest.endpoint)) match {
case Some(action) => {
executeWithType[action._2](action._1, batchRequest)
}
case _ => Future.successful(NotFound)
}
Is this possible at all? I've been trying to fight with it but my understanding of reflection in Scala is really weak, so I'm not sure exactly how I'd go about doing this. I've tried a bunch of classOf and typeTag and Class[_] stuff but I'm basically swinging in the dark. Hoping someone more knowledgeable than I am could help me out.
The big things are:
What needs to go in the second space of the tuple in the value of the Map? How do you pass a Class variable?
How do we use that class-as-a-variable to call a generically typed method?
How do we use that class-as-a-variable to call a generically typed method?
You can't. But I'd like to suggest an alternate solution.
Just define a local class instead of tuples:
class RequestAction[A](action: () => Action[A]) {
def apply(request: BatchRequest) = executeWithType(action, request)
}
val actions = Map(
Seq("POST", "/endpoint1") -> new RequestAction(controller.endpointOne _), // type parameter is inferred
Seq("POST", "/endpoint2") -> new RequestAction(controller.endpointTwo _)
)
val res = actions.get(Seq(batchRequest.method, batchRequest.endpoint)) match {
case Some(action) => action(batchRequest)
case _ => Future.successful(NotFound)
}
(while this depends on code not shown in the question, it looks likely that you can simplify by passing Action[A] instead of () => Action[A]).

How to return Unit from a scala function?

I'm trying to make a function return Unit (this is to implement an RxScala observer), but when I add () to the end of it, I get an error "Application does not take parameters". Here's my code:
val client3MessageStreamObserver: Observable[Message] = client3.messageStream()
client3MessageStreamObserver.subscribe(
m => println("Unexpected message received by client3"),
// callback for handling exceptions
t =>
println("Ex client3: " + t)
// want to make this line work (which it doesn't) which is why
// I need to be able to return Unit.
// client3TestPromise.success(true)
() // error after adding Unit literal here.
)
Why do I get this error after adding () and how can I get rid of it? If I leave it out I get an error saying "Type mismatch: Expected (Throwable) => Unit, actual: (Throwable) => Any)".
Try this:
val client3MessageStreamObserver: Observable[Message] = client3.messageStream()
client3MessageStreamObserver.subscribe(
m => println("Unexpected message received by client3"),
t => println("Ex client3: " + t)
() => ()
)
The third function onCompleted is a function Unit => Unit. So, the parameter is () and then in the return we can explicitly return () or any method returning a () such as println.
OK so I worked this out. Because subscribe expects functions as it's arguments, I needed to wrap multiple instructions in braces to make a code block, i.e.:
val client3MessageStreamObserver: Observable[Message] = client3.messageStream()
client3MessageStreamObserver.subscribe(
// single instruction function doesn't require braces
m => client3TestPromise.failure(new RuntimeException("Unexpected " +
"message received by client3")),
// multi-instruction function does require braces
t => {
println("Ex client3: " + t)
client3TestPromise.success(true)
}
)

Unclear notation in Scala code snippet

I am going through the Principels of Reactive Programming course at Coursera and noticed few times a notation which I cannot completely comprehend. So I hope you can help me to understand.
Here is the code snippet:
def retry(noTimes:Int)(block: => Future[T]): Future[T] = {
val ns: Iterator[Int] = (1 to noTimes).iterator
val attempts: Iterator[Future[T]] = ns.map(_ => () => block)
val failed = Future.failed(new Exception)
attempts.foldLeft(failed) ((a, block) => a recoverWith {block()})
}
It is not clear to me why in the attempts value definition it is not simply ns.map(_ => block) ?
Type of the attempts value is Iterator[Future[T]] and map as it written in the snippet seems to me should produce Iterator[() => Future[T]]. Could you help to grasp it?
With this:
ns.map(_ => block)
block would be executed directly, that's not what the author would want.
Similar to Call-By-Value parameter.
However, with this:
ns.map(_ => () => block), it is similar to Call-By-Name parameter, meaning that the block code would be executed only when explicitly called in the underlying function.
If I correctly remembered, the author of the course was saying something like:
"Sit down, take a coffee and deeply analyse the function in order to figure out why we need to execute the block code lazily" ;)
UPDATE-------
In the wrapping method's signature, block is declared as a call-by-name parameter:
block: => Future[T]
Therefore, the Future[T] well corresponds to () => block explaining why:
val attempts: Iterator[Future[T]] is not val attempts: Iterator[() => Future[T]]

Avoiding default logic for case partial function

I have the following code in multiple places in my application
(i: Option) => {
case Some(i) => // doSomething with i
case None =>
}
The doSomething will vary in each location, but any time I have a None I don't want to do anything.
Is there an easy way to avoid the use of case None => using implicits or otherwise?
If you are discarding the result, then you can use foreach:
o.foreach(i => doSomething(i))
If you need the result of doSomething, then use map:
o.map(i => doSomething(i))
You can use a map or a foreach - these won't do anything if your Option is a None. The difference between the two is that map will return an Option while foreach returns a Unit
iOpt.map(i => /* doSomething with i */) // does nothing and returns a None if iOpt is a None

Params list in Scala function. Can someone explain the code?

Can someone explain the Scala code used in trait Secured of playframework sample app zentask:
def IsAuthenticated(f: => String => Request[AnyContent] => Result) = Security.Authenticated(username, onUnauthorized) { user =>
Action(request => f(user)(request))
}
I've just started to learn Scala and can not figure out this sequence f: => String => Request[AnyContent] => Result . What does it mean? I can not find any examples in manuals that use several => in place of parameters list for function.
What am I missing?
Maybe it's easier if you add some parantheses:
f: => (String => (Request[AnyContent] => Result))
f is a call-by-name parameter; it's a function that takes a String and returns: a function that takes a Request[AnyContent] and returns a Result.
f is a function that, given a String will produce a function that waits for a Result[AnyContent] to provide a Result.
Then at line 2. you pass to f the userparam, which must be a String and you pass the request param to the resulting function.
This way of passing parameters is called currying. A both short and a bit more complex example can be found there: http://www.scala-lang.org/node/135