Why I and my company have moved away from Scala. An honest critique.

classic Classic list List threaded Threaded
115 messages Options
1 ... 3456
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
Hi Hossein,
I thank you for pointing out that my English is hard to parse. To my defence, I'm an ordinary enterprise developer who wants to work for 8 hours but gets work for 10 hours. Hence I have to work overtime for any time spent in discussions. I agree that my posts are brainstorm, could be thought out better and sometimes I leak in some terminology discrepancy. Which in a result is possibly not helpful and can be considered selfish. Because you are all busy as well. I don't want to use the fact that I'm not a native speaker because I consider it a shame that my English is poor. I know that you are for sure busy but if you could just blindly copy blocks with the worst formulations to my email I would find it helpful (or anybody else), don't burn time with explanations. It would help me to improve. I will try to be more precise next time.

I was careless in using "static dispatch" and "dynamic dispatch". It seems to be somewhat central to the discussion and I will try to clarify to see if we can agree on it.

At high level if we disregard compiler and JIT optimization, to my knowledge, every call on JVM except static methods is a dynamic dispatch (implemented as virtual methods). The correct method to call is resolved at runtime, it is what enables polymorphism.

There are 2 different places for polymorphisms to consider in the context of implicit conversions. One happens on an input argument to implicit conversion itself. And the second is on an input argument to a target polymorphic method (nothing surprising). 

I was using "static dispatch" (no polymorphism) and it can be misleading. But I meant that the observable effect is the same like static dispatch (disregarding performance). At the high level it is still dynamic dispatch. But implicit conversion returns a new instance of the required type and the relation to the original input type is lost. Hence there is effectively no polymorphism in a target polymorphic method on a value (object) received from an implicit conversion.

My knowledge about optimizations is limited but I believe that many implicit conversions are inlined by JIT Optimizer (if simple) and effectively end-up as a static dispatch. But it is based on heuristics hence not all are optimized. I think it is easier to disregard these optimizations because observable behaviour has to be the same (otherwise optimizations wouldn't make a sense). @inline annotation can be used to make optimization more predictable but typically it is better to leave it to optimizer. Overhead of implicit conversions is probably so small that it is hard to measure anyway.

As well JIT can optimize across virtual methods boundary (unlike C++ if nothing changed). It analyses loaded classes and if it determines that there is only a single possible virtual call it will inline it. If I have type A and a polymorphic method in terms of A, and there is no subtype of A with overrides, then all calls in a polymorphic method to A methods can be inlined. And I still can have implicit conversions to A.

It would be great if anybody could confirm my understanding of optimizations in the context of simple implicit conversions (no type parameters).

If my explanation is hard to parse let's try code with inline comments. I already posted similar illustrative code but it represented more points at once. Code can be copy/pasted directly to REPL.

class Foo {
  def message(): Unit = println("Foo is shown")
}

/** This is what I mean by a target polymorphic method.
  * It is written in terms of Foo.
  * If Foo has no subtypes than message() from Foo can be inlined here?
  * I believe yes.

  * If input to show(foo: Foo) comes from an implicit conversion to Foo
  * it will always print "Foo is shown". But call to foo.message is
  * dynamic dispatch (polymorphic) nevertheless without optimizations.
  */

def show(foo: Foo): Unit = foo.message()

/** Unrelated to Foo.
  * Obvious that "Bar is shown" is never printed
  * in the target polymorphic show(foo: Foo) below.
  * Inlining optimization still apply? I believe yes.
  *
  * Implicit conversion toFoo can be used and means
  * that "Foo is shown" is printed in show(foo: Foo)
  * for any value of type Bar and its subtypes.
  * No polymorphism here for Bar in show(foo: Foo) method
  * because it returns new instance of Foo hence there
  * is no way how to get back to Bar from show(foo: Foo).
  * It is very important point to realize but shouldn't be
  * surprising because the same happens with explicit conversions.
  */

class Bar {
  def message(): Unit = println("Bar is shown")
}
object Bar {
  implicit def toFoo(bar: Bar): Foo = new Foo()
}

/** Extends Bar and "inherits" toFoo through implicit search.
 *  But it still doesn't have subtype relation to Foo.
 *  But it can use implicit conversion to it.
 *  Again it is obvious it can't participate
 *  in show(foo: Foo) polymorphism (no relation to Foo)
 *  and "Baz1 is shown" is never printed by it.
 *  Inlining optimization still apply? I believe yes.
 */

class Baz1 extends Bar {
  override def message(): Unit = println("Baz1 is shown")
}

// Only here we get subtype polymorphism in show(foo: Foo)
// It cancels inlining optimization in show(foo: Foo)
// because now there are 2 implementations of message()

class Baz2 extends Foo {
  override def message(): Unit = println("Baz2 is shown")
}

// Prints "Foo is shown"

val bar = new Bar
show(bar)
    
// Prints "Foo is shown" regardless
// it has its own message "Baz1 is shown".

val baz1 = new Baz1
show(baz1)

// The show method can be called with any subtype of Foo
// and now polymorphism will kick-in. 
// Prints "Baz2 is shown"

val baz2 = new Baz2
show(baz2)

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
In reply to this post by Naftoli Gugenheim
I find that particularly interesting in light of the fact that the c# docs seemingly call using a Baz where a Bar is expected an implicit conversion.

Interesting. Terminology is a mess across languages. On JVM it is implicit cast towards supertype (as well known as upcasting or widening a type, i.e. less specific type) and explicit cast towards subtype (downcasting, narrowing a type, more specific type).

(JVM, at the end in Casting Objects)
https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

C#
https://msdn.microsoft.com/en-us/library/ms173105.aspx

It reminds me about one problem I typically encounter. Juniors tend to think in terms of superset and subset. Hence type having more methods is superset => supertype. And conversely type up the hierarchy has less methods hence it is subset => subtype (or superclass and subclass respectively).

It takes time to realize that super/sub reflects amount of polymorphic methods a type can be accepted in. And till this view is not changed to a view what a polymorphic method accepts in, it causes problems to understand variance as well. It wouldn't hurt to cover it in documentation otherwise as soon as junior meets sub/super he can get lost.

You might think these are basics but than you would be surprised about a theory level in enterprise. At least based on my experience, I shouldn't extrapolate.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Seyed H. HAERI (Hossein)
In reply to this post by oss.mlists
Hi Petr,

> I thank you for pointing out that my English is hard to parse.

Didn't mean to be picky on it. Only apologising myself in case of
misunderstanding...

> At high level if we disregard compiler and JIT optimization, to my
> knowledge, every call on JVM except static methods is a dynamic dispatch
> (implemented as virtual methods). The correct method to call is resolved at
> runtime, it is what enables polymorphism.

I don't know that about JVM. But, Scala is that way. Java was that way
too the last time I looked into it. That's the entire selling point of
dismissing pointers and explicit references.

I won't be surprised if the compiler can be hoped for putting clever
optimisations to do the dispatch at compile-time. But, that can't be
relied on as a principle.

Cheers,
--Hossein

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
Hi Hossein,
In other words and taking optimizations out of the picture. From a program behaviour perspective, I don't see any difference between a dynamic dispatch (virtual call) which always resolves to the same method and a single dispatch. The only difference between them is performance. I would like to get corrected if I'm wrong. Maybe some runtime hackery with reflection and such but I would disregard these.

I believe I have shown you examples which always resolves to the same message() on Foo with implicit conversions.

However, as I said implicit search very closely resembles subtyping/inheritance/polymorphism in many aspects. We can override inherited method in a subtype with a method which returns covariant type and it will work in polymorphism. The same way valid implicit conversion can return covariant type. In this case it will be polymorphic in a target polymorphic method. I would say it is expected behaviour.

We can't override inherited method in a subtype with a method which accepts contravariant input types. Technically it would be possible but method overloading gets more love (prioritized feature) in both Java and Scala because otherwise there would be ambiguity between overloaded and overridden method. Valid implicit conversion can accept contravariant input type though. I can imagine this one can be confusing if defined like in my example below but it is correct nevertheless. But not something I would do.

And to complete it, if a type extends some type A and has as well valid implicit conversion to type A than implicit conversion is ignored because implicit conversions are searched only if subtyping fails.

My experience is that variance is not well understood concept between mainstream developers, even this basic one without type parameters. I would say it is basic OOP knowledge and applies the same for Java and Scala. It is one reason many (most?) learn generics only to be able to use collections.

object ImplicitConversionVariance {
  class Foo {
    def message(): Unit = println("Foo is shown")
  }

  def show(foo: Foo): Unit = foo.message()

  class Blah extends Foo {
    override def message(): Unit = println("Blah is shown")
  }

  class Bar1
  class Bar2 extends Bar1 {
    def message(): Unit = println("Bar2 is shown")
  }
  object Bar2 {
    // Bar1 is contravariant to Bar2 (Bar2 extends Bar1).
    // It is valid from type substitution perspective
    // and this implicit will be used to convert Bar2
    // even it looks like it applies for Bar1.

    // It returns Blah which is covariant to Foo (Blah extends Foo).
    // It is valid type substitution as well.
    // Because of it foo.message() in target show(foo: Foo)
    // is polymorphic and resolves to message() in Blah.
    
    // It can be understood like it is "inherited" from Bar1.
    // If it would be defined in Bar1 companion it would use
    // Bar1 as input type as well and would be a valid conversion
    // during implicit search as well.
    implicit def toBlah(bar: Bar1): Blah = new Blah()
  }

  def run(): Unit = {
    val bar2 = new Bar2()
    // It prints "Blah is shown" because of polymorphism
    show(bar2)
  }
}

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
In reply to this post by Seyed H. HAERI (Hossein)
Hi Hossein,
here is is an article for Golang as OOP.

My Golang like example models only the containment but lacks inheritance. In Golang message method in A would be shadowed by B message method. I'm not Golang programmer so I'm sorry if I miss any detail. I have just wanted to show that implicit conversions can model similar but limited type substitution based on containment like Golang. It is implicit mechanic regardless how we would call it. I think it can help to understand how to use implicit conversions properly.

> About GolangLike code
> Hmm... Where does the above code manage to avoid dynamic dispatch? 
> From what I can see, it has solely not used one.

It uses dynamic dispatch but it always resolves to the same message method on A because A has no subtypes. In Golang it is statically linked at compile time. Java and Scala have to wait on runtime to possibly optimize it.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
> anything that just magically transparently happens
> is a disaster waiting to happen

Now Robert just has to avoid using any of Java DI frameworks, avoid aspects and frameworks/libs with bytecode manipulation, serialization/deserialization based on reflection and all sorts of such lookups on runtime and he selects a set of annotations with high attention.
 
His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
> Scala implicits are generally misunderstood. Most of hate posts I see miss 
> the point of them and use them wrong. 

> ... which is another way for saying they are comparably much less 
> intuitive than subtyping. 


I don't want to deny it. But I don't know where intuition stops and familiarity starts. E.g. for me it is actually more intuitive why I shouldn't model Rectangle(a, b) => Square(a) compared to making
Rectangle(a, b) subtype of Square(a) where both are immutable and without behaviours, just records with fields.


> I have just look at the documentation... 

> That's a very fair point. And, I think that might very well be one of 
> the reasons why Robert initiated this thread


Maybe it is honest critique, but unfortunately it is hard to get anything useful for me from his post outside of... total disaster, it's true. I would be very interested in actual details how implicits and macros were used so that I could judge for myself if it was legitimate use which went wrong in the end, lack of knowledge or something else.

Sometimes I witness that implicits are good defense hammer just for the sake to be defensive for whatever reason (typically to avoid effort to learn something new), without even trying to understand them. Java developer can routinely use various kinds of magic and implicit contexts but as soon as he hear that something is implicit compared to his supposedly simple, clean and totally type safe language he gets hart attack. I then like to ask him if he knows that arrays in Java are covariant and if he pays attention to it during code review. It changes nothing but it typically gives me an idea.

My main problem is that I can't just point dev to Scala documentation knowing he will come back fully understanding implicits.
And I don't super love interop with Java collections either (all those asScala, asJava). 

"We found that implicits float around in our code interacting in strange ways that were non-deterministic and opaque to reading the code"

It sounds disastrous. After 2 years I can't remember actual problem with them outside of understanding them. I don't deny that problems exists, I don't deny their properties, as you could see I'm open to fair discussion to understand them. We use implicit conversions sparingly, we have a few of KeyValue(key, value) => (key, value) kind + what comes from libs. I find them very useful.

Actually I would say that implicits should be opaque to reading the code. They are named implicits after all for a reason. It really looks to me like misuse with implicits having important logic, side-effects.
But that itself suggests that more effort is needed to document them with best practices.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Jasper-M
In reply to this post by kraythe
Hi,

You might be happy to learn that people are actively looking for ways to help protect developers from themselves:
https://github.com/lampepfl/dotty/pull/2060
https://github.com/lampepfl/dotty/pull/2065

Kind regards,
Jasper

Op zondag 12 februari 2017 18:16:49 UTC+1 schreef kraythe:
I work in a company that uses the Playframework and Akka to implement a business system. For a long time i was trying to push the implementation towards Scala and away from java. However, I have ultimately given up on that effort and have almost completed refactoring the work to Java. Here is why. 

First of all the learning curve on Scala is very steep but unnecessarily so. Scala syntax is very brief and but that isn't what holds up the learning curve, nor is it the functional programming concepts, functions as first class entities. These are in fact the good facets of Scala. Pattern matching is absolutely awesome, immutable collections are something that Java is really lacking. In short there is a ton of good things in Scala that attract a developer from Java. But the problem is Scala shoots itself in the foot. 

Without too much fanfare I will declare that Implicit conversions and Macros make the language very difficult to learn and, outside the academic world, almost inaccessible to business. Implicit conversions and indeed the entire 'implicit" keyword is just lethal to the learning curve as well as code maintenance. In a business world where effort is judged in ROI, anything that just magically transparently happens is a disaster waiting to happen. In fact such disasters do happen. We found that implicits float around in our code interacting in strange ways that were non-deterministic and opaque to reading the code. The beginner looking at a method wonders, "wait how can you call that method on that object?" Then they think and say "oh there is an implicit somewhere in some of my imports somewhere down the tree that convert the type. Its obscure, opaque, confusing and the antithesis of everything that an experienced business developer wants. I used to think that it was just a matter of tooling but IntelliJ has actually decent scala tooling and still implicits are a total disaster. Second problem is Macros. Like implicits they make things happen that are difficult to discern by looking at the code. The introduction of both of these and their rampant use in the language is, in my opinion, going to push Scala to be yet another niche language like lisp, scheme, Erlang and so on. 

Secondly is the compilation tooling and interaction with java. Scala interacts transparently with java. Well, at least that is what the promotional materials say. In practice to achieve that interaction is a major PITA and I am not talking about flat bread here. Conversions of types require gymnastics. For example, try passing a list of Scala longs to a java method that takes a list of java.util.Long objects. Gymnastics. The function lambdas are non translatable so you cant just pass a Scala lambda to a java function that takes a java.util.Function. You can doctor this with ... wait for it ... an implicit conversion that wraps one into the other. Sigh. In our codebase we had tons of code in both languages and it was just a nightmare going between the two. The tooling doesn't help either because SBT gets in some wacked out logic loops and simply rebuilds the whole project multiple times. After years of Scala development SBT is still slow, and in such a bad state that it isn't even at 1.0. 

I think Scala has become too academic. Too controlled by those with PhDs. in computer science figuring out what they can do, rather than wondering if they actually should do these things and as a result the language has abandoned some of its roots. It started out as an alternative to Ruby and Java. It was a statically bound deterministic language with functional and Object oriented concepts but it has now strayed into things that happen "magically" and code that is generated with Macros. I personally think one of two things will happen. Either the maintainers of Scala will reverse this direction and get back to basics, dump the implicits and macros and find more deterministic ways to do things. Or, quite frankly, it will die on the vine as another Erlang, Lisp, Node.js or you name it. A language used in a small limited sector for a few projects but without wide acceptance. 

I, for one would think that is a shame, a horrible waste. Scala could be the next super language if academics stop messing with it like mad scientists with a new toy. Until then, I cant have my whole staff down six months learning scala. 

-- Robert, 
-- Principal Software Architect. 

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

oss.mlists
In reply to this post by oss.mlists
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Oliver Ruebenacker

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Rex Kerr-2
You can still have implicits all over the place and not fall into this particular trap, though.  In my JSON library, you still get implicit conversions but because they're typeclasses or typeclass-like at least, they don't apply everywhere.  So:

scala> val strings = Seq("salmon", "cod", "herring", "perch")
strings: Seq[String] = List(salmon, cod, herring, perch)

scala> Json.Arr(strings)
<console>:49: error: overloaded method value apply with alternatives:
  (xs: Array[Double])kse.jsonal.Json.Arr <and>
  (aj: Array[kse.jsonal.Json])kse.jsonal.Json.Arr
 cannot be applied to (Seq[String])
       Json.Arr(strings)
            ^

scala> Json(strings)
res48: kse.jsonal.Json = ["salmon", "cod", "herring", "perch"]


But this isn't the only solution.  Why have a `Json.arr` method if you can implicitly convert the sequence?  The problem is that when you have too many ways to do the same thing, you can mix and match and get undesired outcomes.

 --Rex


On Fri, Mar 31, 2017 at 8:48 AM, Oliver Ruebenacker <[hidden email]> wrote:

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Alvaro Carrasco
In reply to this post by Oliver Ruebenacker
I don't know that this has anything to do with implicits. Just with understanding the play json api (maybe docs could be improved). 

Json.arr(...) is intented to take repeated values, as in `Json.arr("one", "two", "red", "blue")`. That's just the defined API and knowing that, it is only natural that when giving an array to a function that constructs json arrays from individual elements, you would get a nested array.

If you want to "transform" a Seq to an array the API is this: Json.toJson(strings)

That said, this one is related to implicits and pretty annoying:

scala> Json.arr(Seq("a", "b"):_*)
<console>:25: error: type mismatch;
 found   : Seq[String]
 required: Seq[play.api.libs.json.Json.JsValueWrapper]
       Json.arr(Seq("a", "b"):_*)

Kinda breaks the illusion. Not sure if there's a way around it.


2017-03-31 9:48 GMT-06:00 Oliver Ruebenacker <[hidden email]>:

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Oliver Ruebenacker

     Hello,

 You would like to have something that translates a Seq[T] into a JsArray, butJson.toJson gives you a JsValue.

     Best, Oliver



On Fri, Mar 31, 2017 at 12:15 PM, Alvaro Carrasco <[hidden email]> wrote:
I don't know that this has anything to do with implicits. Just with understanding the play json api (maybe docs could be improved). 

Json.arr(...) is intented to take repeated values, as in `Json.arr("one", "two", "red", "blue")`. That's just the defined API and knowing that, it is only natural that when giving an array to a function that constructs json arrays from individual elements, you would get a nested array.

If you want to "transform" a Seq to an array the API is this: Json.toJson(strings)

That said, this one is related to implicits and pretty annoying:

scala> Json.arr(Seq("a", "b"):_*)
<console>:25: error: type mismatch;
 found   : Seq[String]
 required: Seq[play.api.libs.json.Json.JsValueWrapper]
       Json.arr(Seq("a", "b"):_*)

Kinda breaks the illusion. Not sure if there's a way around it.


2017-03-31 9:48 GMT-06:00 Oliver Ruebenacker <[hidden email]>:

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Alvaro Carrasco
Ah that's true. That's a good point, not sure what the right play json API would be for that. Only way I know is this:

scala> Json.arr(Seq("a", "b").map(x => x:Json.JsValueWrapper):_*)
res5: play.api.libs.json.JsArray = ["a","b"]

And that's terrible.


2017-03-31 10:21 GMT-06:00 Oliver Ruebenacker <[hidden email]>:

     Hello,

 You would like to have something that translates a Seq[T] into a JsArray, butJson.toJson gives you a JsValue.

     Best, Oliver



On Fri, Mar 31, 2017 at 12:15 PM, Alvaro Carrasco <[hidden email]> wrote:
I don't know that this has anything to do with implicits. Just with understanding the play json api (maybe docs could be improved). 

Json.arr(...) is intented to take repeated values, as in `Json.arr("one", "two", "red", "blue")`. That's just the defined API and knowing that, it is only natural that when giving an array to a function that constructs json arrays from individual elements, you would get a nested array.

If you want to "transform" a Seq to an array the API is this: Json.toJson(strings)

That said, this one is related to implicits and pretty annoying:

scala> Json.arr(Seq("a", "b"):_*)
<console>:25: error: type mismatch;
 found   : Seq[String]
 required: Seq[play.api.libs.json.Json.JsValueWrapper]
       Json.arr(Seq("a", "b"):_*)

Kinda breaks the illusion. Not sure if there's a way around it.


2017-03-31 9:48 GMT-06:00 Oliver Ruebenacker <[hidden email]>:

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.




--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute


--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: Why I and my company have moved away from Scala. An honest critique.

Vlad Patryshev
In reply to this post by Oliver Ruebenacker
Same in this case:

scala> val seq = List("a", "b", "c")

seq: List[String] = List(a, b, c)


scala> val arr = Array(seq)

arr: Array[List[String]] = Array(List(a, b, c))


Thanks,
-Vlad

On Fri, Mar 31, 2017 at 8:48 AM, Oliver Ruebenacker <[hidden email]> wrote:

     Hello,

  I think this one is a gem. I love Play's JSON library for its power and conciseness. It relies heavily on implicit conversions and implicit parameters. Occasionally, it can go wrong:

import play.api.libs.json.Writes.StringWrites
import play.api.libs.json.{JsArray, Json}

val strings = Seq("one", "two", "red", "blue")

def getModelList: JsArray = Json.arr(strings)

  Doesn't this look like the most straight-forward creation of a JSON Array of Strings? Actually, it creates an Array that contains another Array:

[ [ "one", "two", "red", "blue" ] ]

     Best, Oliver



On Thu, Mar 9, 2017 at 2:48 PM, <[hidden email]> wrote:
> His beginner developers are well trained and doesn't tend to use short method versions instead of having to pass serdes explicitly with this version.
 
The code with it compiles but where <String, String> comes from? It is totally obvious from the code itself, right?

I forgot to point out that if there is anything bad with Scala implicit values than Java hidden runtime implicit values are even worse. I spent quite a bit of time with lovely "java.lang.ClassCastException: [B cannot be cast to java.lang.String". I realized at that point I got spoiled by Scala. It was a bit funny because I couldn't figure out how it can compile but fails on runtime. I didn't had config and it defaults to Serde[Array[Byte]] I never need. I don't need runtime configuration for serdes. I think it is what one gets if language is missing features. they're filled in by ecosystem or some worse pattern.

Petr

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.



--
Oliver Ruebenacker
Senior Software Engineer, Diabetes Portal, Broad Institute

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "scala-user" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
For more options, visit https://groups.google.com/d/optout.
1 ... 3456