Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Additional Types #36

Closed
placrosse opened this issue Sep 8, 2014 · 12 comments
Closed

Additional Types #36

placrosse opened this issue Sep 8, 2014 · 12 comments

Comments

@placrosse
Copy link

Consider adding Unsigned variants of existing types
(unsigned Bytes, Shorts, Ints, Longs)

@non
Copy link

non commented Sep 8, 2014

We could pull these from Spire if we wanted, e.g. UByte.

@non
Copy link

non commented Sep 8, 2014

The biggest drawback I see with including this type is that we probably wouldn't be able to change the standard library to interoperate with it in useful ways, which would raise questions about what including it really did.

I'm hoping that we can modularize Spire, which would make folks more likely to pull in unsigned number types when they need them.

@puffnfresh
Copy link

@non 👍

@soc
Copy link

soc commented Oct 15, 2014

@non Would it make sense to have different typeclass instances for arithmetic operations on Byte, e. g. where one does signed arithmetic, one does unsigned, one does overflow checks, etc. instead of adding more types?

@non
Copy link

non commented Oct 15, 2014

So the type class idea is interesting. One problem I foresee is that Byte already has a + method on it, so either we'd have to use alternate operators or something else would have to happen to be able to easily do unsigned arithmetic with Byte instances.

If you have an idea about how to do this then let me know -- I'd be interested to see how it might work.

@soc
Copy link

soc commented Oct 15, 2014

Well, you could get rid of all operations defined on primitive types ... will probably be a pretty large job and with questionable compatibility.

@ebruchez
Copy link

Is it wise to to make it easier to use the plethora of existing number types and further to add more number types to the language?

Doug Crockford makes the case in this recent talk that JavaScript made a good call having only one number type. It's just that the wrong type was chosen, and he suggests a new single, decimal number type called DEC64.

I realize that this approach might be a bit antagonistic to static typing but I find myself wishing that Scala were simpler here. What if Scala had only one or two basic number types with reasonable semantic, and the other types would be restrictions on those defined at the library level? Is there any value in this?

I also wish that by default, and maybe without enabling flags, only maybe a Dec type and a Long type were available. Other types make sense for dealing with protocols, performance optimizations, and scientific applications. And there is Java compatibility… So am not suggesting that removing the existing types would be desirable in the short term. But I would be happy seeing them behind flags!

Too radical?

@propensive
Copy link

It's not that radical, though I know that Erik has some concerns about
DEC64. He's probably the best person to give a critique of that.

We already have value classes, and I think we could provide new number
types like DEC64 by wrapping a Long, and redefining all the appropriate
operations so that they manipulate the underlying 64 bits to do the right
thing. It wouldn't be as efficient as "native" Long operations, but it at
least wouldn't have the cost of boxing.

But on a syntactic level, Typelevel could do better. Currently, Scala
supports D, F and L (plus we have Z and S in Typelevel Scala) to
indicate how number literals should be interpreted. These are hardwired
into the parser, and aren't extensible. But they could be, in the same way
that string contexts are. We would just need a way of parsing number
literals in such a way that they could later be interpreted as value
classes.

Here's a casual suggestion for a way that that might happen:

  1. Change the parser to parse number literals as string context
    applications, with the postfix letter somehow encoded into the string
    context prefix. e.g. 3.1415926535897932384626m would be parsed as if you'd
    written number_m"3.1415926535897932384626".
  2. Define standard string context macros to Predef for the familiar
    primitive types (L, F, D, Z, S) which simply instantiate the
    literals. Because they're macros, it should be as efficient as if you had
    just written the literal.
  3. (Probably the most difficult bit) Tidy up details like error messages
    and (range) positions.
  4. New "primitives" can be introduced using more StringContext macros (or
    maybe don't even bother with macros) which instantiate value classes.
  5. If all that can be made to work, we've got an extensible system akin to
    string contexts for number literals. Then we could possibly retrofit the
    concept of NumberContexts to avoid piggybacking on top of StringContexts
    for something that isn't really anything to do with strings.

Thoughts, anyone? I might give this a go...

Jon

On 21 November 2014 19:02, ebruchez [email protected] wrote:

Is it wise to to make it easier to use the plethora of existing number
types and further to add more number types to the language?

Doug Crockford makes the case in this recent talk
https://www.youtube.com/watch?v=PSGEjv3Tqo0 that JavaScript made a good
call having only one number type. It's just that the wrong type was
chosen, and he suggests a new single, decimal number type called DEC64
https://github.com/douglascrockford/DEC64.

I realize that this approach might be a bit antagonistic to static typing
but I find myself wishing that Scala were simpler here. What if Scala had
only one or two basic number types with reasonable semantic, and the other
types would be restrictions on those defined at the library level? Is there
any value in this?

I also wish that by default, and maybe without enabling flags, only maybe
a Dec type and a Long type were available. Other types make sense for
dealing with protocols, performance optimizations, and scientific
applications. And there is Java compatibility… So am not suggesting that
removing the existing types would be desirable in the short term. But I
would be happy seeing them behind flags!

Too radical?


Reply to this email directly or view it on GitHub
#36 (comment).

Jon Pretty | @propensive

@non
Copy link

non commented Nov 22, 2014

I really like the idea of "pluggable numeric literals". I'm not sure how hard that would be to support, but it definitely makes sense. We might want to create a NumberContext rather than piggy-backing on StringContext however.

So, as @propensive suggests, I'm fairly critical of Crockford's DEC64 proposal. I'm not in a position to write a full rebuttal right now, but here's a quick list of bullet points:

  1. Different users have different requirements. It's appropriate to have different types here.
  2. Standardizing on just one fixed-width format guarantees that code with buggy arithmetic will be the norm, with no way to opt for safety/correctness.
  3. Ignoring IEEE-754's decimal standard does not inspire confidence.
  4. The spec doesn't have any discussion of errors/error analysis.
  5. The spec doesn't seem to sufficiently describe/constrain implementations.
  6. Even if we want one type to rule them all, I don't necessarily trust Crockford to design it.

Like I said, I don't necessarily have time to comprehensively analyze and critique DEC64. But I definitely don't think it would be the right move for Scala (Typelevel or otherwise) to standardize on it, especially since it is not a native type on the JVM.

@non
Copy link

non commented Nov 22, 2014

Of course, as an author of a library that adds many more numeric types, and promotes generic numeric programming, you could probably expect that this would be my response! 🎱

@milessabin milessabin added this to the Parked milestone Aug 12, 2016
@milessabin
Copy link
Member

To resurrect this issue, please rework it as an issue/PR against Lightbend Scala (ie. scala/scala).

@SethTisue
Copy link
Member

see SIP-26, scala/docs.scala-lang#548

milessabin pushed a commit that referenced this issue Jul 31, 2017
Non local returns aren't eliminated after inlined in 2.11 or 2.12

```
⚡ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.

scala> @inlune def foo(a: => Any) = if ("".isEmpty) a else ""
<console>:11: error: not found: type inlune
       @inlune def foo(a: => Any) = if ("".isEmpty) a else ""
        ^

scala> @inline def foo(a: => Any) = if ("".isEmpty) a else ""
foo: (a: => Any)Any

scala> class InlineReturn { def test: Any = foo(return "") }
defined class InlineReturn

scala> :javap -c InlineReturn#test
  public java.lang.Object test();
    Code:
       0: new           #4                  // class java/lang/Object
       3: dup
       4: invokespecial #32                 // Method java/lang/Object."<init>":()V
       7: astore_1
       8: getstatic     #36                 // Field $line4/$read$$iw$$iw$.MODULE$:L$line4/$read$$iw$$iw$;
      11: aload_1
      12: invokedynamic #59,  0             // InvokeDynamic #0:apply:(Ljava/lang/Object;)Lscala/Function0;
      17: invokevirtual #63                 // Method $line4/$read$$iw$$iw$.foo:(Lscala/Function0;)Ljava/lang/Object;
      20: goto          44
      23: astore_2
      24: aload_2
      25: invokevirtual #66                 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
      28: aload_1
      29: if_acmpne     39
      32: aload_2
      33: invokevirtual #69                 // Method scala/runtime/NonLocalReturnControl.value:()Ljava/lang/Object;
      36: goto          41
      39: aload_2
      40: athrow
      41: goto          44
      44: areturn
    Exception table:
       from    to  target type
           8    20    23   Class scala/runtime/NonLocalReturnControl
```

```
⚡ ~/scala/2.11.8/bin/scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.

scala> @inline def foo(a: => Any) = if ("".isEmpty) a else ""
foo: (a: => Any)Any

scala> class InlineReturn { def test: Any = foo(return "") }
defined class InlineReturn

scala> :javap -c InlineReturn#test
  public java.lang.Object test();
    Code:
       0: new           #4                  // class java/lang/Object
       3: dup
       4: invokespecial #13                 // Method java/lang/Object."<init>":()V
       7: astore_1
       8: getstatic     #19                 // Field .MODULE$:L;
      11: new           #21                 // class InlineReturn$$anonfun$test$1
      14: dup
      15: aload_0
      16: aload_1
      17: invokespecial #24                 // Method InlineReturn$$anonfun$test$1."<init>":(LInlineReturn;Ljava/lang/Object;)V
      20: invokevirtual #28                 // Method .foo:(Lscala/Function0;)Ljava/lang/Object;
      23: goto          39
      26: astore_2
      27: aload_2
      28: invokevirtual #31                 // Method scala/runtime/NonLocalReturnControl.key:()Ljava/lang/Object;
      31: aload_1
      32: if_acmpne     40
      35: aload_2
      36: invokevirtual #34                 // Method scala/runtime/NonLocalReturnControl.value:()Ljava/lang/Object;
      39: areturn
      40: aload_2
      41: athrow
    Exception table:
       from    to  target type
           8    26    26   Class scala/runtime/NonLocalReturnControl

scala> :quit
```
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

8 participants