Integer literals are usually of type
Int
, or of typeLong
when followed by aL
orl
suffix.
from Scala Language Specification
OK. 1.234574812938T
should have been 1.234574812938.T
.
Integer literals are usually of type
Int
, or of typeLong
when followed by aL
orl
suffix.
from Scala Language Specification
OK. 1.234574812938T
should have been 1.234574812938.T
.
This seems totally unnecessary to me. What about:
//Int extension methods
def million: Int = thisInt * 1000000
def billion: Long = thisInt.toLong * 1000000000l
def trillion: Long = thisInt.toLong * 1000000000000l
def quadrillion: Long = thisInt.toLong * 1000000000000000l
//Long extension method
def million: Long = thisLong * 1000000l
def billion: Long = thisLong * 1000000000l
And then for any non-simple, many digit numbers just compose using the above, Int literals and + or -.
This works for round numbers (10 million) but fails for arbitrary numbers like 1000_0531.
Hello,
I’m not sure how often people have non-round integer literals with more then three digits in their code, but if you really need something:
Welcome to Scala 2.12.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_171).
Type in expressions for evaluation. Or try :help.
implicit class SuperLong(l: Long) { def m: Long = 1000Ll; def m(l2: Long) = 1000Ll + l2 }
defined class SuperLong
import scala.language.postfixOps
import scala.language.postfixOps
123 m
res0: Long = 123000
123 m 456 m 789
res1: Long = 123456789
Best, Oliver
val specialNum = 10.million + 531
Just for fun
:))
if bigdecimal literal exists( Bigdecimal literal )
there will be easy way to get digit count.
static int integerDigits(BigDecimal n) {
n = n.stripTrailingZeros();
return n.precision() - n.scale();
}
So we can easyly make “||” operator:
def || (b:BigDecimal):Bigdecimal = {
v*integerDigits(b)+b
}
It will works for arbitrary numbers like 1000b || 0531b
:))
Seriously. I don’t think there is something better than string interpolation.
Unfortunately it doesn’t work with pattern matching.
I would like to note that a lot of the suggestions here:
These other suggestions don’t address the fact that underscores can also make a binary or hex literal more readable.
For example (I’m going to draw heavily from Python’s syntax and examples here):
val magicNumber = 0xCAFE_BABE
val flags = 0b_0011_1111_0100_1110
but what if you need 10_200_531
instead? 10.million + 200.thousand + 531
? This can become quite verbose.
I think the main objection to a compile-time string interpolator was macros’ future. Maybe we could solve that while avoiding a language change by adding the string interpolator(s) to the standard library. We already have the f interpolator.
Incidentally, how does Dotty use the standard library when it has macros?
If you try to use any Scala 2 macro like the f"" interpolator in Dotty, you’ll get a MethodNotFoundException at runtime (we should probably detect this at compile time).
Lots of good suggestions here.
I am completely in favor of allowing _
in numeric literals. If someone wants to open an issue laying down the desired syntax, we can act on this quickly.
Regarding string interpolators: I am not sure why they need to be whitebox macros. The type of a string interpolator such as f
could well be (Any*)String
. It is then the job of the interpolator to refuse any argument that does not conform to its format string. So f
is still a macro, but not a whitebox macro.
Concerning BigDecimal literals themselves, I think only extensible solutions are worth considering. Don’t stop at BigDecimals. Can we have a scheme where we can have arbitrary user-defined types that allow some form of numeric literal? One way to do it is to say that a numeric literal N
is of type T
if
T
is the expected type at the point where the literal is definedLiterally[T]
defined for T
wheretrait Literally[A] {
def fromString(s: String): A
}
So, the following would both work, assuming BigDecimal
and BigInt
define Literally
instances that
convert strings of digits to the type itself.
val x: BigDecimal = 1234567890.9
(123: BigInt)
They would expand to
val x: BigDecimal = BigDecimal.literally.fromString("1234567890.9")
(BigInt.literally.fromString("123"): BigInt)
This assumes that BigDecimal
has a companion object like
object BigDecimal {
implicit def literally: Literally[BigDecimal] = new {
def fromString(digits: String) = new BigDecimal(digits)
}
}
We can improve on this solution by making fromString
a macro that checks the digits
string
for syntactic validity.
One issue is how to define a syntax for general numeric literals N
without mentioning the result type. One candidate syntax would be:
This would allow for many different ways to write numbers (even IP addresses would be covered!). It does not cover floating point numbers with exponents, but I am not sure these are worth generalizing.
I like this proposal, but having to rely on the expected type makes for verbose expressions, e.g:
(1232432432: BigDecimal) + (3432432: BigDecimal)
I would rather write:
1232432432bd + 3432432bd
This would also be consistent with the fact that today I can write 3432432l
. We could allow this by rewriting:
123foo
as:
NumericalContext("123").foo
That would nicely mirror the string interpolator syntax.
It looks very useful.
It will be great if it works with pattern matching.
If NumericalContext provide unapply method:
n match {
case 1232432432bd => println("great")
}
If I understand correctly
https://scala-lang.org/files/archive/spec/2.12/13-syntax-summary.html
In the code:
1 match {
case -1 => println("-1")
case _ => println("_")
}
The '-'s is part of literal.
So may be, we can use the '+'s or '-'s to define type aliace:
type Bd = BigDecimal
val a = Bd+1234567890.9
val b = Bd-1234567890.9
a + b match {
case Bd+0 =>
case _ =>
}
It will be work with any letters:
For example
val date = Dd+1d.2m.2004y_00h.5min.24sec
me too.
Seth (SIP committee member)
None of the proposals so far give me octal literals back.
Unless I can use leading underscore for that purpose?
val permissions = _755
Given that the prefix 0x
means hex, can we do 0o
for octal and 0b
for binary literals? This would give
val permissions = 0o755
This is in accordance with ECMAScript 6 and Julia, both of which has 0b
and 0o
literals besides the standard 0x
.
@smarter I feel generalized suffix strings and NumericLiteralContexts mostly generalize a wart. I always found 123l very bad, already from a typographic standpoint. 123L is a bit better, but still ugly. Types are good. Writing
val x: BigInt = 1234567890
is longer than
val x = 1234567890bi
but also much clearer. Furthermore, in many cases types are known from the context, in which case the suffix-less syntax is shorter anyway.
@odersky I was planning to submit a small SIP to deprecate a lower-case l
to mark Long
s. I’ve mistaken l
for 1
enough times that I think the change outweighs the incompatibility cost: I would call it a bug that it’s possible at all, and I really can’t think of any good reason why there is this one single incidence of case-insensitivity in the language; why the choice?
I’ve already done the trivial code changes in Dotty, which was a fun first experiment.
But… I prefer your more general proposal!
@som-snytt If we decide to perpetuate the madness of allowing l
to indicate Long
s, then maybe we could give you an O
suffix for octal literals?