Coder Social home page Coder Social logo

paddymahoney / scala-records Goto Github PK

View Code? Open in Web Editor NEW

This project forked from scala-records/scala-records

0.0 3.0 0.0 186 KB

Labeled records for Scala based on structural refinement types and macros.

License: BSD 3-Clause "New" or "Revised" License

Scala 100.00%

scala-records's Introduction

Records for Scala Build Status Join the chat at https://gitter.im/scala-records/scala-records

Scala Records introduce a data type Rec for representing record types. Records are convenient for accessing and manipulating semi-structured data. Records are similar in functionality to F# records and shapeless records, however, they do not impose an ordering on their fields. Most relevant use cases are:

  • Manipulating large tables in big-data frameworks like Spark and Scalding
  • Manipulating results of SQL queries
  • Manipulating JSON, YAML, XML, etc.

Records are implemented using macros and completely blend in the Scala environment. With records:

  • Fields are accessed with a path just like regular case classes (e.g. rec.country.state)
  • Type errors are comprehensible and elaborate
  • Auto-completion in the Eclipse IDE works seamlessly
  • Run-time performance is high due to specialization with macros
  • Compile-time performance is high due to the use of macros

Quick Start

To create a simple record run:

import records.Rec

scala> val person = Rec("name" -> "Hannah", "age" -> 30)
person: records.Rec{def name: String; def age: Int} = Rec { name = Hannah, age = 30 }

Fields of records can be accessed just like fields of classes:

if (person.age > 18) println(s"${person.name} is an adult.")

Scala Records allow for arbitrary levels of nesting:

val person = Rec(
 "name" -> "Hannah",
 "age" -> 30,
 "country" -> Rec("name" -> "US", "state" -> "CA"))

They can be explicitly converted to case classes:

case class Country(name: String, state: String)
case class Person(name: String, age: String, country: Country)
val personClass = person.to[Person]

As well as implicitly when the contents of records.RecordConversions are imported:

import records.RecordConversions._
val personClass: Person = person

In case of erroneous access, type errors will be comprehensible:

scala> person.nme
<console>:10: error: value nme is not a member of records.Rec{def name: String; def age: Int}
              person.nme
                     ^

Errors are also appropriate when converting to case classes:

val person = Rec("name" -> "Hannah", "age" -> 30)
val personClass = person.to[Person]

<console>:13: error: Converting to Person would require the source record to have the following additional fields: [country: Country].
       val personClass = person.to[Person]
                                  ^

Including Scala Records in Your Project

To include Scala Records in your SBT build please add:

libraryDependencies += "ch.epfl.lamp" %% "scala-records" % <version>

Support

It is "safe" to use Scala Records in your project. They cross-compile against all minor Scala versions after 2.10.2. We will give our best effort to fix all the bugs promptly until we find a more principal, and functioning, solution for accessing semi-structured data in Scala. For further details see this page.

Current Limitations

For All Scala Versions

  1. Record types must not be explicitly mentioned. In case of explicit mentioning the result will be a run-time exception. In 2.11.x this would be detected by a warning. For example:

    val rec: Rec { def x: Int } = Rec("x" -> 1)
    rec.x // throws an exception
    
    • Fixing SI-7340 would resolve this issue.
    • A workaround would be to write a case class for a record type.
  2. Records will not display nicely in IntelliJ IDEA. IntelliJ IDEA does not support whitebox macros:

    • Writing a custom implementation for IntelliJ would remove this limitation.
  3. In the Eclipse debugger records can not be debugged when conversions to case classes are used. For this to work the IDE must to understand the behavior of implicit macros.

  4. In the Eclipse debugger records display as their underlying data structures. If these structures are optimized it is hard to keep track of the fields.

For Scala 2.10.x

  1. All record calls will fire a warning for a reflective macro call.

[warn] 109: reflective access of structural type member macro method baz should be enabled [warn] by making the implicit value scala.language.reflectiveCalls visible. [warn] row.baz should be (1.7)


To disable this warning users must introduce `import scala.language.reflectiveCalls` in a scope or set the compiler option `-language:reflectiveCalls`.
2. Least upper bounds (LUBs) of two records can not be found. Consequences are the following:

+ If two queries return the same records the results can not be directly combined under a same type. For example, `List(Rec("a" -> 1), Rec("a" -> 2))` will not be usable.

## Performance

Scala Records compile asymptotically faster and run asymptotically faster than type-based approaches to records (e.g. `HMaps`). For up-to-date benchmarks check out [this repo](https://github.com/scala-records/scala-records-benchmarks).

## Helping Further Development

In case you have any desires for new functionality, or find errors in the existing one, please report them in the [issue tracker][issues]. We will gladly discuss further development and accept your pull requests.

[issues]: https://github.com/scala-records/scala-records/issues

## Contributors
Scala Records are developed with love and joy in the [Scala Lab][scalalab] at [EPFL][epfl] in collaboration with Michael Armbrust from [Databricks][databricks]. Main contributors are:
+ Vojin Jovanovic (@vjovanov)
+ Tobias Schlatter (@gzm0)
+ Hubert Plocziniczak (@hubertp)

[databricks]: https://databricks.com/
[scalalab]: http://lamp.epfl.ch/
[epfl]: http://epfl.ch/

scala-records's People

Contributors

gzm0 avatar vjovanov avatar hubertp avatar densh avatar heathermiller avatar gitter-badger avatar

Watchers

James Cloos avatar Patrick Mahoney avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.