Akka Streams Graph DSL notation - akka

I used graph dsl to create some stream processing jobs based on some example code I saw. Everything runs great, I am just having trouble understanding the notation: (updated for 2.4)
def elements: Source[Foos] = ...
def logEveryNSink = // a sink that logs
def cleaner: Flow[Foos, Bars, Unit] = ...
def boolChecker(bar: Bar)(implicit ex: ExecutionContext): Future[Boolean] = ...
val mySink = Sink.foreach[Boolean](println(_))
val lastly = Flow[Bars].mapAsync(2)(x => boolChecker(x).toMat(mySink)(Keep.right)
val materialized = RunnableGraph.fromGraph(
GraphDSL.create(lastly) { implicit builder =>
baz => {
import GraphDSL.Implicits._
val broadcast1 = builder.add(Broadcast[Foos](2))
val broadcast2 = builder.add(Broadcast[Bars](2))
elements ~> broadcast1 ~> logEveryNSink(1)
broadcast1 ~> cleaner ~> broadcast2 ~> baz
~> broadcast2 ~> logEveryNSink(1)
ClosedShape
}
}
).run()
I understand the implicit builder that is included, but Im uncertain what the baz represents in { implicit builder => baz => { .... is it just an implicit name for the entire shape?

The GraphDSL.create method is heavily overloaded to take in many variants of amounts of input shapes (including 0). If you pass in no initial shapes, then the signature of the buildBlock function arg (the body where you actually define how the graph is to be built) is as follows:
(Builder[NotUsed]) => S
So this is simply a Function1[Builder[NotUsed], S], that is, a function that takes an instance of a Builder[NotUsed] and returns a Shape instance which is the final graph. The NotUsed here is synonymous with Unit in that you are saying that by not passing in any input shares that you do not care about the materialized value of the output graph being produced.
If you do decide to pass in input shapes, then the signature of that buildBlock function changes a bit to accomadate the input shapes. In your case, you are passing in 1 input shape, so the signature of buildBlock changes to:
(Builder[Mat]) => Graph.Shape => S
Now, this is essentially a Function1[Builder[Mat], Function1[Graph.Shape, S]], or a function that takes a Builder[Mat] (where Mat is the materialized value type of the input shape) and returns a function that takes a Graph.Shape and returns an instance of S (which is a Shape).
Long story short, if you pass in shapes, then you also need to declare them as bound params on the graph building block function but as a second input function (hence the additional =>).

Related

Applying implicit generic parameters to a list via ClassTag

I would like to apply a function to all objects in a list, where all objects in the list inherit from a common class. In this function, I would like to use an implicit class to ensure that the correct operation is applied based on the object's type.
For example, I want to ensure that all Employee objects in a list are converted using the employeeConverter below. Calling convert with the Employee directly works just fine, but applying convert to a list of Employee objects is a compiler error.
import scala.reflect.ClassTag
object Example {
abstract class Person { def age: Int }
case class Employee(age: Int) extends Person
class Converter[T] { def convert(t: T) = (t,t) }
def convert[T <: Person:ClassTag](p: T)(implicit converter: Converter[T]) =
converter.convert(p)
def main(args: Array[String]): Unit = {
implicit val employeeConverter = new Converter[Employee]()
println(convert(Employee(1)))
//println(List(Employee(2)) map convert) // COMPILER ERROR
}
}
The above code correctly prints the following:
$ scalac Example.scala && scala Example
(Employee(1),Employee(1))
However, if I uncomment the line indicated with COMPILER ERROR, I get this compiler error:
Example.scala:20: error: could not find implicit value for parameter converter: Example.Converter[T]
println(l map convert)
^
Is this a problem that can be resolved using ClassTag? How can I modify this example to apply convert to a list?
The compiler needs a little bit of hand-holding in this case. This works:
println(List(Employee(2)) map { e => convert(e) })

Testing interfaces with foq

I am trying to use Foq to testing an interface with Foq.
So far, all examples I have seen for this have been relatively simple, such as the following:
let users = [|{ID = 1; pass = true};{ID = 2; pass= false}|]
type IFoo =
abstract member Bar: int -> bool
//tests with Foq
let dataAccess =
Mock<IFoo>()
.Setup(fun x-> <# x.Bar(users.[0].ID) #>).Returns(users.[0].pass)
.Setup(fun x-> <# x.Bar(users.[1].ID) #>).Returns(users.[1].pass)
.Create()
The examples have been sourced from 'Testing with F# - Mikael Lundin'
I have also researched this through a bit of googling (this link was helpful - http://trelford.com/blog/post/Foq.aspx)
However, the real Interfaces I want to test are the following:
type IParameters =
abstract member ParameterDate : int->string->DateTime
type IDataSource =
abstract member MortParameters: IParameters
I have tried a number of different ways to test these (e.g. defining a function with a signature of int->string to be used as the input to the setup. Alternatively, having the return value as a string->DateTime and the Setup as just an integer.
My question is really the following: When testing interfaces using Foq, how can I extend the testing to interfaces with function signatures of any general length (e.g. a->b->c->d->e etc.)
Since ParameterDate a property with a function type, you could just set it up as a property that returns a lambda value. See an example of property set-up in Foq. This should be easy to modify for your case:
let instance =
Mock<System.Collections.IList>()
.Setup(fun x -> <# x.Count #>).Returns(1)
.Create()
However, I guess you would lose the ability to have a strict mock with fixed expectations on the function inputs.
To enforce only expected inputs for the function returned by the mock property you could provide a function like this:
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Invalid mock input"
I would probably stop here, but if you're working with code where you need to verify a function was called, as opposed to just ensuring you get the correct output, you could add a helper like this:
type Verifiable<'a, 'b> (f : 'a -> 'b) =
let called = ref false
member this.Func x =
called := true
f x
member this.Verify() =
if not called.Value then failwith "Mock function was not called"
And here's how you would use it:
let parameterDateMock =
fun i s ->
match i, s with
| 1, "" -> DateTime.Now
| _ -> failwith "Unexpected mock input"
|> Verifiable
let parameters =
{ new IParameters with member this.ParameterDate i s = parameterDateMock.Func i s }
parameters.ParameterDate 1 ""
parameterDateMock.Verify()
Caveat: This only verifies the function was called with at least one parameter. It may have returned another function by currying and not actually run the code in the mock function body. To get around that you'd need a variation of the Verifiable class for every function arity and use the right one in each case.

RSpec: expect array of hashes in class_double recieve

I want to test with RSpec a function my_test. The function calls another class's class method MyHelper.func in rails 4.
I used mock to illustrate func in class MyHelper, and I want to match the argument that func receives with some const values.
I used
expect(<double>).to receive(func).with(arguments)
But one of the const arguments is a hash with more than 2 items. When I test my
function, RSpec throws an error:
received :func with unexpected arguments.
expected: [{"1"=>33.33},{"2"=>33.33},{"3"=>33.33}]
got: [{"2"=>33.33},{"1"=>33.33},{"3"=>33.33}]
Is there a way to match between the two arrays?
The code:
my_hash = [{"1"=>33.33},{"2"=>33.33},{"3"=>33.33}]
notifier = class_double("MyHelper").
as_stubbed_const(:transfer_nested_constant => true)
expect(notifier).to receive(:func).with(my_hash)
This is a bit tricky since you are comparing two things that are not equal when using ==
let(:expected) { [{"1"=>33.33},{"2"=>33.33},{"3"=>33.33}] }
let(:actual) { [{"2"=>33.33},{"1"=>33.33},{"3"=>33.33}] }
expect(actual).to eq(expected) # fails
However, you can define a custom matcher and use it to compare the arguments:
RSpec::Matchers.define :sorted_array_match do |expected|
match do |actual|
expected_hash = expected.inject({}) {|m,(k,v)| m.merge!(k=>v)}
actual_hash = actual.inject({}) {|m,(k,v)| m.merge!(k=>v)}
actual_hash == expected_hash
end
end
it "should work" do
expect(notifier).to receive(:func).with(sorted_array_match(expected))
notifier.func(actual)
end
Note that this converts the array argument into a hash, so it assumes the arguments are arrays containing hashes with different keys. You might need to alter it to fit the actual data.
More info in the RSpec docs.

What is the optimal way (not using Scalaz) to type require a non-empty List?

As I am working a design model, I am torn between two different methods of indicating a parameter of type List must be nonEmpty. I began by using List[Int] with an accompanying require statement to verify the List is nonEmpty.
case class A(name: String, favoriteNumbers: List[Int]) {
require(favoriteNumbers.nonEmpty, "favoriteNumbers must not be empty")
}
I then needed to make the list optional. If the List is provided, it must be nonEmpty. I'm using using Option[List[Int]] with an accompanying require statement to verify, if the Option is nonEmpty, the list must also be nonEmpty.
case class B(name: String, favoriteNumbers: Option[List[Int]]) {
require(
favoriteNumbers.isEmpty || favoriateNumbers.get.nonEmpty
, "when defined, favoriteNumbers.get must be nonEmpty"
)
}
However, I need to use this non-empty List all over the system I am modeling. This means that my code has these same require statements duplicated everywhere. Is there a (non-ScalaZ) way to have a new type, say NeList, which is defined and behaves identically to List, with the only change being an exception is thrown when NeList attempts to be instantiated with no elements?
I tried to Google for this and couldn't find a set of search terms to hone on this area. I either got really simple List how-tos, or all sorts of references to ScalaZ's NEL (Non Empty List). So, if there is a link out there that would help with this, I would love to see it.
If you
def foo[A](x: ::[A]) = "List has length "+x.length
then you insist that the list be nonempty. But of course your lists are all typed as List, so you need a helper method to give you a nonempty list:
implicit class NonEmptyList[A](private val underlying: List[A]) {
def ifNonEmpty[B](f: ::[A] => B): Option[B] = {
underlying match {
case x: ::[A #unchecked] => Some(f(x))
case _ => None
}
}
}
Now you can safely apply the operation to get an Option out. (You could also run side-effecting functions in a foreach-like method.)
Now, this is rather non-idiomatic Scala. But it is safe at compile time (the #unchecked notwithstanding--Scala's compiler isn't quite smart enough to realize that the type parameter hasn't changed).
You could implement a non-empty list yourself with implicit conversions between List[A] and Nel[A]:
case class Nel[A](val head: A, val tail: List[A] = Nil)
implicit def list2Nel[A](list: List[A]): Nel[A] = {
require(!list.isEmpty)
Nel(list.head, list.tail)
}
implicit def nel2List[A](nel: Nel[A]): List[A] = nel.head :: nel.tail
Then you can define your functions where this is needed such that they take a Nel[A] as a parameter:
def f(l: Option[Nel[String]]) = { ... }
And call them with normal lists (assuming the implicit defs are in scope):
f(Some(List("hello", "world")) // works
f(Some(Nil)) // throws IllegalArgumentException
f(None) // works
EDIT: It should be noted that this does not provide compile time guarantees that the List[A] passed in will not be empty. If that's what you want, then get rid of the implicit def list2Nel and require clients of your function to pass in an Nel[A] explicitly, thus guaranteeing at compile time that the list is not empty.
Also, this is a very basic NonEmptyList implementation. A more complete solution is found in scalaz (granted it was specifically requested in the question that scalaz not be used): https://github.com/scalaz/scalaz/blob/series/7.2.x/core/src/main/scala/scalaz/NonEmptyList.scala

Modifying multiple Lists inside a function and returning it in Scala

I have a List of type [T] and [B] in scala, with an object e of type E.
I want to make a function that accepts those three parameters:
def doSomething(t : List[T], b List[B], e : E) {
... }
However I realise that List is immutable, and anything passed to a function is considered as val (not var). But I need to modify t and b and return the modifications back to the caller of the function. Does anyone have any idea how to do this?
I can't go and change the list to array... Because I've been using it everywhere and the file is so big..
You should modify t and b in a functional way using higher order functions like map, filter,... and put the result of them into new vals (e.g. modifiedT, modifiedB). Then you can use a Tuple2 to return 2 values from the method.
def doSomething(t: List[T], b: List[B], e: E) = {
// somehting you want to do
val modifiedT = t.map(...).filter(...)
val modifiedB = b.map(...).filter(...)
(modifiedT, modifiedB) // returns a Tuple2[List[T], List[B]]
}
In the calling method you can then assign the values this way:
val (t2, b2) = doSomething(t, b, e)
Of course it depends on what you mean with "modify".
If this modification is complicated stuff you should consider using view to make calculation lazy to move the time of calculation to a later point in time.