xpresso


Source link: https://github.com/WantedTechnologies/xpresso

xpresso

The pythonic way to code in Java.

xpresso is a Java library inspired by Python. It allows a (near) line-into-line rewrite of a Python code into Java. It's also a great way to prototype your algorithms directly in Java.

xpresso implements in Java familiar pythonic methods (e.g., len, enumerate, split/join, slicing) and coding paradigms (e.g., everything is iterable, list comprehensions, generators, lambda expressions, filtering iterables using predicates and modifying them using functions).

xpresso also offers multiple useful tools, usually one-liners, that save developer's time and make the code more readable: x.String, x.Object, x.Function, x.memo, x.WebService, x.MapReduce, x.go, x.timer, x.Json, x.mysql, x.csv and others.

xpresso: less boilerplate, more fun, more work done.

License: [MIT] ( https://en.wikipedia.org/wikei/MIT_License).

Usage

import com.wantedtech.common.xpresso.x;  x.print("Hello World!");

Main features

Types similar to pythonic ones

import com.wantedtech.common.xpresso.types.*;

Imports: set, dict, list, tuple, DefaultDict, OrderedDict, Bag, HappyFile, HappySQL

Slicable and iterable str type

str city = x.str("New York City");
  x.print(city.slice(4,8));
  Console: York
for (String character : city)  x.print(character);
  Console: N e w  Y o r k

One-line file open

Python:

with open("name.txt","r","utf-8") as f:  #do stuff

xpresso:

try (HappyFile f = x.open("name.txt","r","utf-8")) {
  //do stuff 
}

Works for write/read/append in both text and binary mode.

As in Python, a file opened for reading in text mode is an Iterable of strings:

Python:

for line in f:  print line

xpresso:

for (String line : f)  x.print(line);

Tuples

Python:

my_car = ("Honda", "red", 2010, True)

xpresso:

tuple myCar = x.tuple("Honda", "red", 2010, true);

Dynamic name assignment to tuple elements:

myCar.name("make","color","year","good");
 x.print(myCar.get("good"),myCar.get("make"),myCar.get("year"));
  Console: true Honda 2010

If name method has not yet been called, but get(someName) is called for the first time, then the returned value will be get(i), where i is the smallest index of a remaining unnamed element in the tuple. All the subsequent calls for the same value someName, the same element i will be returned by get(someName).

You can also define and use a typed version of tuple. For example:

tuple3<String,String,Integer> myCar = x.tuple3("Honda", "red", 2010);
  String myCarMake = myCar.left; String myCarColor = myCar.middle; Integer myCarYear = myCar.right;  tuple2<String,tuple3<String,String,Integer>> item = x.tuple2("car",myCar);
  String type = item.key; //or, alternatively String type = item.left; tuple3<String,String,Integer> car = item.value; //or, alternatively tuple3<String,String,Integer> car = item.right;

Neat standard object creation

Python:

trips = ["Dubai","New York","London","Paris","Moscow","London","Saint-Petersburg","New York"]  russian_cities = set(["Moscow","Saint-Petersburg"])  rank = dict(("Moscow":30),("Saint-Petersburg":15),("New York":20),("London":10),("Paris":5),("Dubai":32)) 

xpresso:

list<String> trips = x.list("Dubai","New York","London","Paris","Moscow","London","Saint-Petersburg","New York");
  set<String> russianCities = x.set("Moscow","Saint-Petersburg");
  dict<Integer> rank = x.dict(x.tuple("Moscow",30),x.tuple("Saint-Petersburg",15),x.tuple("New York",20),x.tuple("London",10),x.tuple("Paris",5),x.tuple("Dubai",32));

Functions and predicates

import com.wantedtech.common.functional.*  Function<Object, String> toUpperCaseFun = new Function<Object, String>() {
  public String apply(Object value) {

return value.toString().toUpperCase();
  
}
 
}
;  list<String> tripsUp = x.map(toUpperCaseFun, trips);
 x.print(tripsUp);
  Console: [DUBAI, NEW YORK, LONDON, PARIS, MOSCOW, LONDON, SAINT-PETERSBURG, NEW YORK]
Predicate<Object> containsO = new Predicate<Object>() {
  public Boolean apply(Object value) {

return x.String("o").in(value.toString()) ? true : false;  
}
 
}
;  list<String> tripsO = x.filter(containsO, trips);
 x.print(tripsO);
  Console: [New York, London, Moscow, London, New York]

You don't need to define a new Function class every time you want to transform an iterable in a certain way. You can use the x.Function that automagically wraps any static method of any Java class into a Function:

Function<String,String> myUpper = x.Function(String.class, "toUpperCase");
  iterable = x.map(myUpper, iterable);

The x.Function method can also wrap static methods that take several arguments:

Function<tuple3<String,Integer,Boolean>,Double> mySomeFunc = x.Function(Some.class, "someStaticMethod");
  Function<tuple3<String,Integer,Boolean>,Double> myOtherFunc = x.Function(Other.class, "someOtherMethod");
  Function<tuple3<String,Integer,Boolean>,Double> funcToUse; if (someCondition) {
  funcToUse = mySomeFunc; 
}
 else {
  funcToUse = myOtherFunc; 
}
  double sum; for (element : iterable) {
  sum += funcToUse.apply(x.tuple3(element,intParam,boolParam));
 
}

If in a certain class there're more than one static method with the same name, you need to specify which one of them you want to wrap by providing parameter types:

Function<tuple3<String,Integer,Boolean>,Double> mySomeFunc = x.Function(Some.class, "someStaticMethod", String.class, Integer.class, Boolean.class);

Lambda expressions

Python:

best_cities = reversed(sorted(item for item in rank.items(),lambda x: x[0]))

xpresso:

list<String> bestCities = x.reverse(x.sort(yield().forEach(rank.items()),x.lambdaF("x: x[0]")));

More complex lambda expressions:

Predicate<Object> pr = x.lambdaP("x : f0(f1(x[1])) == '''new york'''",x.lower,x.strip);
Function<Object,Integer> squareFun = x.lambdaF("x : x * x");
  Function<Object,Integer> fun = x.lambdaF("x : x[0] * 10 * (x[1] - f0(x[2])))",squareFun);

Function chains:

Function<Object,Integer> incrementFun = x.lambdaF("x : x + 1");
 Function<Object,Integer> squareFun = x.lambdaF("x : x * x");
  Function<Object,Integer> chainFun = x.chain(incrementFun,squareFun);

chainFun will first increment, then square its input. x.chain(...) can take more than two functions as argument. The last function in the chain has to return the value of the desired output type.

List comprehensions

Python:

foreign_trips_lower = [city.lower() for city in trips if city not in russian_cities]

xpresso:

list<String> foreignTripsLower = x.list(x.<String>yield().apply(x.lower).forEach(trips).unless(x.in(russianCities)));

Python:

cool_cities = dict([(city.upper(),true) for (city, score) in rank.items() if score > 5])

xpresso:

dict<Integer> coolCities = x.dict(x.yield("city","_").apply(x.upper).replace(true).where("city","score").in(rank.items()).when(x.lambdaP("city, score : score > 20")));

Python:

evals = [True if value == "good" else False for value in some_list]

xpresso:

list<Boolean> evals = x.list(x.<Boolean>yield().replace(true).when(x.lambdaP("x : x == '''good'''")).replaceOtherwise(false).forEach(someList));

You can use list comprehensions to extract properties from element objects:

class PlannedTrip {

  int year;
  String city;

 public PlannedTrip(int year, String city) {

this.year = year;

this.city = city;
  
}

 public int getYear() {
 return year; 
}

  public String getCity() {
 return city; 
}
 
}
  list<PlannedTrip> plans = x.list(new PlannedTrip(2015, "Moscow"), new PlannedTrip(2016, "Paris"));
  list<tuple> plansData = x.list(x.yield("year", "city").where("year", "city").in(plans));
  x.print(plansData);
  Console: [(2015, Moscow), (2016, Paris)]

You can also filter the extracted values in the same expression:

list<tuple> plansData = x.list(x.yield("year", "city").where("year", "city").in(plans).when(x.lambdaP("year, city : year > 2015)));
  x.print(plansData);
  Console: [(2016, Paris)]

RESTful web services

Let's suppose we have an object of a class SomeMath which has two methods we would like to publish on the network as RESTful web services, getSum and getProduct:

public class SomeMath() {
  public Double getSum(Double[] values) {
 //we want to publish this one
return x.sum(values);
  
}
  public Double getProduct(Double x, Double y) {
//and this one
return x * y;  
}
  public Double anotherMethod(Double somethingElse) {
//but not this one
return somethingElse;  
}
 
}

In order to convert our SomeMath class into a web service, we simply need to first annotate our two methods we want to call from the network with the @ExposeAs annotation, and then start our web service:

public class SomeMath() {
  public Double getSum(@ExposeAs("values") Double[] values) {

return x.sum(values);
  
}
  public Double getProduct(@ExposeAs("x") Double x, @ExposeAs("y") Double y) {

return x * y;  
}
  public Double anotherMethod(Double somethingElse) {

return somethingElse;  
}
 
}
  WebService ws = x.WebService(new SomeMath(), 8080).start();

That's all! Our web service is up and running. Let's test it. Open the following url in your browser:

http://localhost:8080/SomeMath/getSum?values=5&values=6&values=7 

The output:

18.0 

Now open the following url:

http://localhost:8080/SomeMath/getProduct?x=5&y=10 

The output:

50.0 

If a method returns an output type of more complex classes such as Java's standard Map and List, or xpresso's own list and dict, the output will be a corresponding JSON string.

Generators

Python:

def firstn(n):  num = 0  while num < n:
yield num
num += 1  for i in firstn(500000):  print i

xpresso:

public Generator<Integer> firstn (final int n) {
  return new Generator<Integer>() {

public void generate() {

 int num = 0;
 while (num < n) {

  yield(num);

  num++;
 
}

}
  
}
; 
}
  for (int i : firstn(500000))
x.print(i);

Memoization

As a quick example, let xerox be a Function object whose method apply copies the string "hello" the given number count of times:

Function<Integer, String> xerox = new Function<Integer, String>() {
  public String apply(Integer count) {

return x.String("hello").times(count);
  
}
 
}
;

It's a long to execute function for large values of count.

In order to avoid the long computation for the same value of count, we first create a cached version of xerox using x.memo:

Function<Integer,String> cachedXerox = x.memo(xerox);

The first call of the function. The computation takes a very long time:

x.timer.start();
 String copies = cachedXerox.apply(5000000);
 x.print(x.timer.stop());
  Console: 18.898s

The second call with the same value of count, the result is instantaneous:

x.timer.start();
 String moreCopies = cachedXerox.apply(5000000);
 x.print(x.timer.stop());
  Console: 0.0s

x.memo can be used to cache methods of object of any Java type, not only Function. Notice the usage of the standard x.timer: no additional timer object needs to be created.

Concurrency (beta)

Concurrency in xpresso is inspired by Go and, as a consequence, is extremely simple. First, define a worker as an instance of Predicate:

Predicate<Channel<Integer>> worker = new Predicate<Channel<Integer>>() {
  public Boolean apply(Channel<Integer> channel) {

while (some_condition_true) {

 Integer value = computeValue();
 //compute something in parallel
 channel.send(value);

//send the computed value to the channel

}

return true;

//everything went as expected  
}
 
}
;

Then, define the channel to where the workers should send the computed values as soon as those values are ready:

Channel<Integer> channel = x.Channel(Integer.class);
//this channel only accepts Integer values

Then, start as many concurrent workers as needed:

x.go(worker, channel);
 x.go(worker, channel);
 x.go(worker, channel);
 ...

Finally, retrieve from the channel the values concurrently computed by the workers when those values are needed:

for (Integer value : channel) {
  x.print(value);
 
}

MapReduce (beta)

Let's assume that we have a list of elements we want to process:

list<String> elements = x.list("Map","aNd","ReDuce","arE","aWEsome");

The processing of each element takes a long time (10 seconds), so we want to parallelize the processing on our multicore machine. Let the processing be as follows: if the element starts with an "a", then put it in uppercase and join it with other uppercase elements using "~" as separator; if the element doesn't start with an "a", then put it to lowercase and join it with other lowercase words.

Let's define the Mapper and Reducer:

import com.wantedtech.common.xpresso.experimental.concurrency.Mapper; import com.wantedtech.common.xpresso.experimental.concurrency.Reducer;  static Mapper<String,String> mapper = new Mapper<String,String>() {
  public void map(String input) {

x.Time.sleep(10);
 //the processing of each element takes a long time :-)
if (x.String(input).startsWith("a")) {

 yield("upper", input.toUpperCase());

 
}
 else {

 yield("lower", input.toLowerCase());

}
  
}
 
}
;  static Reducer<String,String> reducer = new Reducer<String,String>() {
  public void reduce(tuple2<String,list<String>> input) {

yield(input.key,x.String("~").join(input.value));
  
}
 
}
;

Our mapper does the transformation of the string case as described above, and our reducer joins the resulting values with the "~".

Our MapReduce setup is now ready, so let's start crunching:

x.timer.start();
 x.print(x.<String,String,String>MapReduce(elements).map(mapper).reduce(reducer), x.timer.stop());
  Console: {
upper:AND~AWESOME~ARE, lower:reduce~map
}
 10.013s

As you can see, the processing of all 5 elements took only about 10 seconds, while we have defined above that the processing of each single element takes 10 seconds.

JSON

Remember the rank dict:

dict<Integer> rank = x.dict(x.tuple("Moscow",30),x.tuple("Saint-Petersburg",15),x.tuple("New York",20),x.tuple("London",10),x.tuple("Paris",5),x.tuple("Dubai",32));

Let's first dump it as a String:

String rankAsString = x.Json(rank).toString();
 x.print(rankAsString);
  Console: {
"New York":20,"London":10,"Saint-Petersburg":15,"Moscow":30,"Dubai":32,"Paris":5
}

Now let's create a copy of the rank dict from its JSON string representation:

dict<Integer> rankCopy = x.String(rankAsString).parseJson();

Compare the original rank dict to the copy:

x.print(x.Object(rank).equals(rankCopy));
  Console: true

CSV

Read from file:

try (HappyFile f = x.open("filename.txt","r","utf-8")) {
  for (list<String> row : x.csv(f)) {

//do stuff  
}
 
}

Or, simply:

list<list<String>> data = x.list(x.csv("filename.txt","r","utf-8"));

Write to file:

try (HappyFile f = x.open("filename.txt","w","utf-8")) {
  for (list<?> row : data){

x.csv(f).writerow(row);
  
}
 
}

Or, simply:

try (HappyFile f = x.open("filename.txt","w","utf-8")) {
  f.write(x.csv(data).toString());
 
}

Write to a StringBuilder:

StringBuilder builder = new StringBuilder();
  for (list<?> row : data) {
  x.csv(builder).writerow(row);
 
}
  String cs = c.toString();

Or, simply:

String cs = x.csv(data).toString();

MySQL

String host = "host:port"; String user = "user"; String password = "password"; String db = "db";  try (HappySQL sql = x.mysql(host, user, password, db)) {
  try (HappySQL sql2 = x.mysql(sql)){

String query = "SELECT ID FROM " +

 "tbl_Employees e " +

 "WHERE e.Name LIKE ?";
for (tuple row : sql.execute(query, "John %")) {

 query = "UPDATE tbl_Employees " +

"SET Promoted = 1 " +

"WHERE ID = ?";
 sql2.execute(query, row.get("ID"));

}
  
}
 
}

Extended String functions

Python:

if "e" in "Hello World":
  #do stuff

xpresso:

if(x.String("e").in("Hello World")) {

  //do stuff 
}

Python:

colorsPattern = "|".join(["black","green","red","white"]);  print colorsPattern  >>> black|green|red|white

xpresso:

String colorsPattern = x.String("|").join(x.list("black","green","red","white"));
  x.print(colorsPattern);
  Console: black|green|red|white

Python:

tokens = "Moscow;London;Paris".split(";")  print tokens  >>> ['Moscow', 'London', 'Paris']

xpresso:

list<String> tokens = x.String("Moscow;London;Paris").split(";");
  x.print(tokens);
  Console: [Moscow, London, Paris]

Transliterate:

String trans = x.String("??????? ??").translit();
  x.print(trans);
  Console: ?i?ëtka bei jing  x.print(trans.stripAccents());
  Console: Cicetka bei jing

Convert unicode to ascii:

String unidec = x.String("??????? ??").unidecode();
  x.print(unidec);
  Console: Chichiotka bei jing

Approximate string comparison:

x.print(x.String("Hello World").similarity("Hello Wold!"))  Console: 91

The output is 100% compatible with FuzzyWuzzy.

Approximate pattern matching:

x.print(x.String("You are cooding in Java.").search("coding"));
  Console: 8

Get similar strings:

list<String> lookAlikes = x.String("apple").lookAlikes(x.list("ape", "apples", "peach", "puppy"),50);
  x.print(lookAlikes);
  Console: [ape, apples]

Tokenization:

String text = "English is hard. It can be understood through tough thorough thought, though.";  for (Sentence s : x.String.EN.tokenize(text)) {
  for (Token t : s) {

x.print(t);
  
}
 
}
  Console: English is hard . It can ...

Part-of-speech tagging

With xpresso you can easily POS tag any English text with the very fast and accurate (~97%) Stanford CoreNLP english-left3words model:

import com.wantedtech.common.xpresso.sentence.Sentence; import com.wantedtech.common.xpresso.sentence.PosTagger; 

Resources

A circular text view for Android Marshmallow.

Android wrapper for logging information.

A quick and easy database manager and viewer plugin library for your DBFlow databases to view, insert, delete, update the tables directly inside your app.

Simplistic example app demonstrating using latest Firebase features. Checkout branches for each feature.

Shade can reduce code related to SharedPreferences operation efficiently using annotation processing.

Linear Timer is a custom view for Android that enables circular progress animation with respect to given duration.

Topics


2D Engines   3D Engines   9-Patch   Action Bars   Activities   ADB   Advertisements   Analytics   Animations   ANR   AOP   API   APK   APT   Architecture   Audio   Autocomplete   Background Processing   Backward Compatibility   Badges   Bar Codes   Benchmarking   Bitmaps   Bluetooth   Blur Effects   Bread Crumbs   BRMS   Browser Extensions   Build Systems   Bundles   Buttons   Caching   Camera   Canvas   Cards   Carousels   Changelog   Checkboxes   Cloud Storages   Color Analysis   Color Pickers   Colors   Comet/Push   Compass Sensors   Conferences   Content Providers   Continuous Integration   Crash Reports   Credit Cards   Credits   CSV   Curl/Flip   Data Binding   Data Generators   Data Structures   Database   Database Browsers   Date &   Debugging   Decompilers   Deep Links   Dependency Injections   Design   Design Patterns   Dex   Dialogs   Distributed Computing   Distribution Platforms   Download Managers   Drawables   Emoji   Emulators   EPUB   Equalizers &   Event Buses   Exception Handling   Face Recognition   Feedback &   File System   File/Directory   Fingerprint   Floating Action   Fonts   Forms   Fragments   FRP   FSM   Functional Programming   Gamepads   Games   Geocaching   Gestures   GIF   Glow Pad   Gradle Plugins   Graphics   Grid Views   Highlighting   HTML   HTTP Mocking   Icons   IDE   IDE Plugins   Image Croppers   Image Loaders   Image Pickers   Image Processing   Image Views   Instrumentation   Intents   Job Schedulers   JSON   Keyboard   Kotlin   Layouts   Library Demos   List View   List Views   Localization   Location   Lock Patterns   Logcat   Logging   Mails   Maps   Markdown   Mathematics   Maven Plugins   MBaaS   Media   Menus   Messaging   MIME   Mobile Web   Native Image   Navigation   NDK   Networking   NFC   NoSQL   Number Pickers   OAuth   Object Mocking   OCR Engines   OpenGL   ORM   Other Pickers   Parallax List   Parcelables   Particle Systems   Password Inputs   PDF   Permissions   Physics Engines   Platforms   Plugin Frameworks   Preferences   Progress Indicators   ProGuard   Properties   Protocol Buffer   Pull To   Purchases   Push/Pull   QR Codes   Quick Return   Radio Buttons   Range Bars   Ratings   Recycler Views   Resources   REST   Ripple Effects   RSS   Screenshots   Scripting   Scroll Views   SDK   Search Inputs   Security   Sensors   Services   Showcase Views   Signatures   Sliding Panels   Snackbars   SOAP   Social Networks   Spannable   Spinners   Splash Screens   SSH   Static Analysis   Status Bars   Styling   SVG   System   Tags   Task Managers   TDD &   Template Engines   Testing   Testing Tools   Text Formatting   Text Views   Text Watchers   Text-to   Toasts   Toolkits For   Tools   Tooltips   Trainings   TV   Twitter   Updaters   USB   User Stories   Utils   Validation   Video   View Adapters   View Pagers   Views   Watch Face   Wearable Data   Wearables   Weather   Web Tools   Web Views   WebRTC   WebSockets   Wheel Widgets   Wi-Fi   Widgets   Windows   Wizards   XML   XMPP   YAML   ZIP Codes