2048 from Rosetta Code


#1

I found this and wanted to give it a try:
https://rosettacode.org/wiki/2048#Scala

But this gives 28 errors. Is there something wrong with my environment, or with the code?


#2

What are the errors you’re getting? My guess would be that this example is incomplete – that it’s depending on libraries you have to include in your .sbt file, but it’s not showing the .sbt file.

(I’ll also opine that it isn’t especially idiomatic Scala code. It probably works, but it looks a lot like Java code that has been translated to Scala.)


#3

I just started again with Scala after being away for a ‘few’ years. And I really did not do anything with GUI’s. So I thought this could be a nice star to get on track againt. It really does something (I hope), is not overly simple, but also not very complex.

But from your comment I understand that this was not my best decision. :wink:

Anyone knows a better example?

Twenty-eight is a bit much, but it starts with:
/home/cecil/scala/Game2048.scala:12: error: type mismatch;
found : () => Unit
required: Runnable
SwingUtilities.invokeLater(() => {
^
/home/cecil/scala/Game2048.scala:25: error: not found: value Game2048
private var (tiles, gamestate)= (Array.ofDim[Tile](side, side), Game2048.State.start)
^
/home/cecil/scala/Game2048.scala:70: error: Any does not take parameters
) if (Option(tiles®©).isEmpty) {
^
/home/cecil/scala/Game2048.scala:82: error: not found: value Game2048
if (gamestate == Game2048.State.won) g.drawString(“you made it!”, 390, 350)
^
/home/cecil/scala/Game2048.scala:83: error: not found: value Game2048
else if (gamestate == Game2048.State.over) g.drawString(“game over”, 400, 350)
^
/home/cecil/scala/Game2048.scala:91: error: Any does not take parameters
val value = tiles®©.value
^
/home/cecil/scala/Game2048.scala:96: error: value getAscent is not a member of Any
val asc = fm.getAscent
^
/home/cecil/scala/Game2048.scala:97: error: value stringWidth is not a member of Any
val (x, y) = (215 + c * 121 + (106 - fm.stringWidth(s)) / 2,115 + r * 121 + (asc + (106 - (asc + fm.getDescent)) /


#4

Hmm. I don’t have access to an IDE at the moment, but when I plug this into Scastie it seems to be compiling successfully. (It’s failing at runtime, but that’s expected given that I’m trying to run a desktop application from a web browser.)

So a different question: how are you compiling this? I’m wondering if the issue is environmental.

That said – as I’ve mentioned before, I personally prefer to build stuff with Web UIs these days. If you have any interest in that, I’d recommend the Scala.js SPA tutorial, which is a very idiomatic example of a client-server web application. Or possibly the Hands-on Scala.js tutorial, which provides more information about building something entirely in the client, which works well for a lot of use cases. (You can now build very sophisticated applications purely client-side, if you don’t need persistence. That’s the way I would personally do something like a 2048 game.)


#5

Are you maybe using an older version of scala? The first type mismatch comes from using a lambda to instantiate a “SAM” (Single Abstract Method) interface, which is only supported since Scala 2.12.


#6

I do not compile it yet. I just run it with ‘scala Game2048.scala’.

I find sbt a bit cumbersome to use. I probably need to dig into sbt.


#7

That is the problem. I am using Debian and there they use 2.11.8. So it is my environment.


#8

Ah. This is another reason to get sbt and start using it – it lets you simply declare your target version of Scala for a project, and auto-downloads it when needed. In my experience, it’s actually pretty unusual to run something directly with the scala command. (I’ve never done so, in six years of professional Scala experience – indeed, I’ve never directly installed Scala in my main development environments.)

I would recommend installing sbt, use the “sbt new” command to generate a new project, and then put this file into there to build and run it. That’s a much more conventional Scala development environment…


#9

That works. The reason I used scala instead of sbt is that I wrote a little mancala engine and with just using scala instead of sbt it runs much faster.
I probably need to dive into how sbt works.
Thanks.


#10

I understood the code is not really scala code, but more translated Java code. What would be a good way to rewrite it?


#11

It’s unlikely that there’s much difference in the speed of the actual program – it’s just that sbt is really slow to boot. It’s a build tool, and isn’t really intended for use at runtime. (I tend to just leave it running in a separate window.)

(There’s also been a fair amount of progress on boot speed, although it’s far from perfect. If this sort of thing matters to you, I recommend looking into “bloop”.)

Well, the biggest difference I notice offhand is that the algorithm does an awful lot of mutable rewriting of structures. The move() function is a classic example: it is mutating the game state under the hood, and then just returning a flag of whether it did something. By contrast, if I was teaching this as a Scala example, I’d want that function to compute the new game state and return it, but not to change any external vars.

Really, that’s the heart of it right there, and it’s a topic that comes up here frequently: when I think of “good” Scala code, it usually tries to minimize the use of non-local vars. You sometimes need them for efficiency, and there are specific cases where they are idiomatic, but (unlike Java) they aren’t a tool I would recommend normally reaching for. Instead, I recommend leaning towards writing “pure” functions (take parameters, return a result, don’t do any side-effects) except when you have to break out of that for practical reasons.


#12

That is what I mend. The overhead from sbt means that with scala the program is already finished, when with sbt it starts executing. I have to evaluate the different possibilities.

I will look in your tips for rewriting.

Thanks.


#13

I suppose, but only because you’re building a toy program in an unusual way – I believe your observed results would be very different for a real program of any serious scale, especially when you’re actually running it rather than developing it. So I don’t recommend generalizing from this observation…


#14

Yes, with continuously having a sbt instamce open it really is a lot less a problem. So I just need to create an extra console with an opened sbt.


#15

Yeah, I pretty much always run that way. (Even when using the IntelliJ IDE I usually have a Terminal window open.)