Practical functional design in Scala?


Practical functional design in Scala?

Hi people, I want to share some thoughts I collected so far while trying to understand intended way to use Scala.

Cases I've seen so far are:

  • use Scala as "better java". Prefer classes to traits, use modern OOP AKA preferring immutable classes and class aggregation. Good example of such style is http://ift.tt/zvT3Jc .
  • Haskell-style, with heavy use of monads and combinators. Largest practical project I've seen is http://ift.tt/1VILicn
  • Dotty compiler. Seems to be most interesting since it is relatively new Scala code with high requirements on performance written by people who should know Scala the best. Sources are here: http://ift.tt/2t5qpDB

Some facts about Dotty sources:

  • they do not use functions that return functions
  • they do not use IO, State or other monads that wrap functions
  • no typeclasses
  • no parser combinators
  • no implicit fields in objects that have to be imported
  • no implicit conversions
  • VERY limited set of types for implicit parameters (see below)
  • no cake pattern 🙂

Most code is organized in functions or methods with following signature:

def fun(arg1, arg2...)(implict ctx: Context): Result 

Where Context is huge object combined from many traits which serves two functions:

  • mutable global state.
  • application configuration. It provides implementations for multiple traits therefore working as dependency injection

So, what do I want to say…

Twitter-style OOP is solid and well-known with well-known problems of object aggregation – that to get working code we need to assemble large object tree. Which complicates code isolation and testing

Haskell-style uses excess CPU/GC which makes it less practical for writing fast software. Also it is quite complicated to write and understand.

Dotty takes another approach by separating data, algorithms and configuration. Naive approach to write code as functions is not that flexible: given

def f(v: Int) = g(v) 

you can't add new argument to g() w/o adding new arguments to entire call stack, you can't replace g() with another implementation except for passing it as function argument both for sake of configuration or testing.

Implicits won't really help because they are resolved by type – to provide implicit instances, caller must have them as implicit parameters, import them or pass them directly to second argument list.

Single Context type helps but is that really the best way? It breaks encapsulation by feeding functions more data than they need, it must be assembled correctly for unit tests, it shadows real dependencies of the function. Other issues are described there in scaladoc: http://ift.tt/2s6tdve

Well. Can dotty sources be used as an example of intended design for Scala applications? Is there better way to manage dependencies in programs that are composed of functions and not of objects? What design do you use?

Please, comment.

Submitted June 24, 2017 at 02:20PM by Scf37
via reddit http://ift.tt/2tF38FA

How to reduce nesting on chain futures


How to reduce nesting on chain futures

Most of the time my Future[T] operations are dependent to previous future in the chain. I am using flatMap function with pattern matching most of the time. Such as;

findUser(userId).flatMap { case None => Future.successful(NotFound("No user with given id")) case Some(user) => findAddress(user.addressId).flatMap { case None => Future.successful(NotFound("No address with given id")) case Some(address) => findCity(address.cityId).flatMap { case None => Future.successful(NotFound("No city with given id")) case Some => Future.successful(Ok) } } } 

with this way i am able to return an object related with the problem, all branchings are being handled. But downside of this approach in my opinion (and my code reading pleasure) it is getting nested a lot. Also if the lines are too long it is impossible to track which case statement is which even with a proper formatting. So that goes to the right-bottom side of the editor.

The other way one would suggest might using for comprehension. Below is kind of a equivalent of the code above. But the difference is for-comp one is throwing an exception if the if-guard is not satisfied. Also it returns an option to use which wherever i want to use i need to call get method (which i don't want to do);

val items = for { user <- findUser(userId) if user.isDefined address <- findAddress(user.addressId) if address.isDefined city <- findCity(address.cityId) if address.isDefined } yield (user.get, address.get, city.get) 

Again one may suggest catching the exception but as i read from many sources catching exceptions are considered not good. Also the exception wouldn't provide which case statement didn't satisfy the condition.

Same thing applies for return statements as well. As myself coming from java and .net based languages, i am inclined to use;

val user = Await.result(findUser(userId), timeout) if (user.isEmpty) { return Future.successful(NotFound("No user with given id")) } val address = Await.result(findAddress(user.get.addressId), timeout) if (address.isEmpty) { return Future.successful(NotFound("No address with given id")) } val city = Await.result(findUser(address.get.cityId), timeout) if(city.isEmpty) { return Future.successful(NotFound("No city with given id")) } Future.successful(Ok) 

which is definitely out of question in my understanding. First of all it makes the code-block blocking, secondly again it forces me to use get values and uses return blocks which are similar with the throwing exceptions in the matter of cutting the execution short.

Haven't been able to find an elegant solution to this. I am currently going with the nested approach which makes it harder to read

Thanks

Submitted June 23, 2017 at 07:05PM by deliganli
via reddit http://ift.tt/2tW8Vpu

Akka http vs Play WS – What is the current state and which one to use?


Akka http vs Play WS – What is the current state and which one to use?

I know that the plan for play is to include akka http as the backend and that is completed in play 2.6. Since I am new to both akka and play, I am seeing that akka is kind of more lower level than play, with play being a full fledged framework.

My questions are

  • Akka http has a routing DSL. How is this different from Play?
  • Since play ws is a separate independent component, is it more preferable to use play ws instead of akka http?
  • This is speculation, but is play ws easier to learn when compared to akka http since it is a higher level abstraction on top of akka http.

We want a robust/scalable framework to build REST APIs and in my search, both seem to be good. Can someone demystify this for me.

Submitted June 23, 2017 at 02:31PM by ivanovich_ivan
via reddit http://ift.tt/2t14Xj7

About ammonite, tracking and why I won’t use it


About ammonite, tracking and why I won’t use it

A few things first:

  • I like the idea behind ammonite. I have always wondered about using a Scala-REPL as an everyday shell, so the idea interests me.
  • I haven't actually used ammonite yet. The specific syntax used by ammonite doesn't excite me much.
  • However, I have followed the project with interest, since its inception, hoping that I might use it someday in some form.

While looking at the changelog for 0.9.0, I noticed that the library has started "remote-logging" aka tracking user activity. To quote the changelog:

Ammonite now anonymously logs the times you start a REPL session and the count of how many commands get run. This is to allow the author to understand usage patterns and prioritize improvements. If you wish to disable it, pass in the –no-remote-logging command-line flag or the remoteLogging=false argument to Main.

So, the tracking is on by default with options to disable it.

I think this is a very bad practice security-wise. I don't want my programs to dial home and report my activity (even if anonymously), and much less so, my shell or a library that I import into my projects.

I raised a polite complaint on github and received an equally polite reply that this wont-be-fixed. However, I find the reasoning to be absurd. Users need to pay to remove a feature. There's a word for that type of software: ransomware.

After that issue was closed, I just decided to ignore ammonite and go on about my life. But the author and the library are popular and always in the news, which makes it hard to ignore 😛 Hence the rant.

Submitted June 22, 2017 at 01:03PM by hrjet
via reddit http://ift.tt/2sT1MsY