4 ms·
Something that I enjoy very much in Scala is sealed traits + case classes. sealed trait Food case class FishTaco(size: FishSize) extends Food case class
by amzans 8y ago
Something that I enjoy very much in Scala is sealed traits + case classes.
sealed trait Food
case class FishTaco(size: FishSize) extends Food
case class Burger(numPatties: Int) extends Food
case class Spaghetti(sauce: PastaSauce) extends Food
It’s like Enums + Data Classes on steroids. You can pass around and transform your data as usual, but if you forgot to handle a specific case when doing pattern matching you’ll get a compile warning. For example in the following case:
input match {
case Burger(patties) => ...
case Spaghetti(sauce) => ...
}
The compiler will happily yell at you something like:
warning: match may not be exhaustive.
It would fail on the following input: FishTaco(_)
Little things such as this one help reasoning about your program since you can rely on the types describing what is possible and what is not.
- deleted 8y ago[deleted]
- Rapzid 8y agoIf you like that kinda thing you should check out F# as well. The IDE experience/speed is much better for F# IMHO, but I have a lot of respect for the concepts behind both. And of course they ride on completely separate massive ecosystems, so you can't exactly swap them out willy-nilly.. I wish I could figure out why my IDE experience with Scala and IntelliJ(IDEA) was so darn sluggish. Also hoping they jump on the language server protocol bandwagon in the future.
- brianberns 8y agoYep, these are called "discriminated unions" in F#. I think most functional programming languages have something similar. The underlying concept is "algebraic data types": You can compose types as products (tuples or records) and sums (discriminated unions) of simpler types. From there, you can actually use algebra on types, which is pretty mind-blowing. For example, we can define a generic sum type called Either: Either a b = Left a | Right b You can think of Either as the sum of types "a" and "b": a + b. Tuples are product types, so you can use the distributive property of multiplication over addition to establish that: (a, Either b c) = Either (a, b) (a, c) Or algebraically: a * (b + c) = (a * b) + (a * c) This is one of those areas where category theory is actually useful for programmers.
- megaman22 8y agoI want desperately to start moving a legacy C# codebase to F#. The problem is that I'm currently the only one that understands the C# codebase, other developers on the project struggle to understand the JS front-end, and flail on contact with the back-end. I'm at severe risk of making myself an Expert Beginner indispensable piece, but I don't know how to move forward with what I have to work with.
- wjossey 8y agoBased on what you’re saying, adding greater understanding to the current codebase is problem #1, which you’ll need to solve before going to F#. Language migrations require two things, at minimum: [1] A really firm understanding of the business logic the code is performing (which can really be simplified to, do you have a deep understanding of “the business”) [2] An understanding of the edge cases. #2 is often only captured in the code, and these regressions end up being the thing that cause lots of bumps along the way with business teams. Knowledge gets lost so easily, or silo’d in distant parts of the business, that the code really becomes the “living history” of the business. I don’t have a lot of good solutions for you. Migrating languages is tough business, but I’d potentially think about starting a “lunch and learn” with some colleagues to do high level code walkthroughs. This could help to distribute knowledge, and build a better understanding of what you already have. The process of prepping can help you to also document what it might take to do the migration, so you can better make the case to any superiors you need to get buy in from. Good luck!
- gonesurfing 8y agoIn the spirit of leveraging the type system, you could try doing some type-first development. If possible, carve a logical module or sub-system out of your existing code base and then attempt to represent the data and functions for that module in F# types. Don't implement any of the functions, just see if you can describe the data and operations using the type system. Tomas Petricek describes this approach really nicely in his post "Why type first development matters". This has a the following benefits: - It helps you review and clarify what the existing code does. - It will force you to name the data and operations explicitly. - You won't be distracted by actually implementing the operations. - You have a succinct description of the module that you can discuss with other developers. - It divides the migration into manageable chunks. You could challenge yourself to educate team members, through the type system. You may also find some of the techniques from the book "Working Effectively with Legacy Code" useful. Updated: Removed links as comment was not posting.
- s4vi0r 8y agoDepending on when you were using Scala, it could have to do with abuse of implicits; back in like 2012/2013ish there we a bit of a craze with using implicits everywhere which would make any sort of IDEs job incredibly tough and compilation painfully slow. I write Scala in Emacs at the moment so I can't speak to intellij but Emacs certainly isn't the fastest editor around and I've yet to run into major issues. The core team also finally realized how important tooling is and recently dedicated a team (a bunch of teams?) to working on language server based intelllisense which is nice. I'd highly encourage anybody who last used Scala a while ago and didn't enjoy it to give it another shot at some point in the future. Lots of improvements over the past few years (and some really cool stuff coming up with Scala 3) make Scala IMO easily one the best languages around.
- Rapzid 8y agoIt was within the past 6 months and I was up-to-date on IDEA and Scala. I was running it on OSX though, so that may have had something to do with it.. It's hard to recall, but I may have run this by another team member and he didn't think it was unusual. Perhaps Microsoft has just spoiled me with C#, F#, and TypeScript tooling :|
- hocuspocus 8y agoFirstly, IDEA's default JVM settings are a bit conservative. The default 750MB maximum heap size is too low for any non-trivial Scala project. Here's someone who attempts to explain all settings: https://github.com/FoxxMD/intellij-jvm-options-explained https://github.com/FoxxMD/intellij-jvm-options-explained Secondly, IDEA's SBT plugin works pretty well, use it if that's not the case yet, and put a reasonable .jvmopts file in your project. SBT can still be slow and there no magic cure for that (even though it's constantly improving). Some of my coworkers use bloop instead: https://scalacenter.github.io/bloop/ https://scalacenter.github.io/bloop/ That said, Scala is indeed jumping on the LSP bandwagon, and it's already supported by Dotty out of the box.
- MrBuddyCasino 8y agoThat looks similar to Rust's enums. The compiler enforces exhaustiveness in pattern matching. enum WebEvent { // An `enum` may either be `unit-like`, PageLoad, PageUnload, // like tuple structs, KeyPress(char), Paste(String), // or like structures. Click { x: i64, y: i64 }, }
- willtim 8y agoOCaml was a big influence on the design of Rust.
- justinpombrio 8y ago> It’s like Enums + Data Classes on steroids. Also known as algebraic data types, which have been around for decades and can be found in Ml/OCaml, Haskell, and Rust.