Xtend

Preview:

DESCRIPTION

Язык программирования Xtend

Citation preview

Язык программирования

Xtend

• Язык общего назначения

Xtend

• Язык общего назначения• Транслируется в Java 5

Xtend

• Язык общего назначения• Транслируется в Java 5• ООП + немного ФП

Xtend

• Язык общего назначения• Транслируется в Java 5• ООП + немного ФП• Простота изучения (намного проще

Scala), схожесть с Java

Xtend

• Язык общего назначения• Транслируется в Java 5• ООП + немного ФП• Простота изучения (намного проще

Scala), схожесть с Java• Библиотека – тонкая прослойка над

Java (≈100 классов) + Guava

Языки JVM

Yeti

Erjang

Frege

Языки JVM

Yeti

Erjang

Frege

Языки JVM

Yeti

Frege

Языки JVM

Языки JVM

Языки JVM

Кол-во вопросов на SO

Java Scala Groovy Clojure JRuby Jython Xtend Kotlin Mirah Gosu Fantom Ceylon Yeti X101

10

100

1000

10000

100000

1000000457101

17592

6564 5612

17481143

82

2314

9 8 7 63

Опрос

No ; and ()

class Main { def static void main(String[] args) { println(5.toString) }}

Translation to Java

import org.eclipse.xtext.xbase.lib.InputOutput;

@SuppressWarnings("all")public class Main { public static void main(final String[] args) { String _string = Integer.valueOf(5).toString(); InputOutput.<String>println(_string); }}

val, var and type inference

val n = 5

for (i : 1..n) { var str = i.toString println(str)

str = ...}

val, var and type inference

val int n = 5

for (int i : 1..n) { var String str = i.toString println(str)

str = ...}

Type inference

val list = new ArrayListlist.add(1)list.add("text")list.add(true)

println(list)

Type inference

val list = new ArrayListlist.add(1)list.add("text")list.add(true)

println(list)

Какой тип у ArrayList?

Type inference

val list = new ArrayList<Serializable>list.add(1)list.add("text")list.add(true)

println(list)

Type inference

val list = new ArrayList<Comparable<?>>list.add(1)list.add("text")list.add(true)

println(list)

Everything is an expressiondef static readData() { val data = try { fileContentsToString('data.txt') } catch (IOException e) { "dummy data" }

println(data)

data}

switch

def String describe(Object x) { switch x { Integer case x > 0 : "Positive integer" String : "String" List<?> case x.empty : "Empty list" List<?> : "Non-empty list" default : x.class.simpleName }}

Классы

@Dataclass Person { val String firstName val String lastName val int age

def void sayHello() { println('''Hello, my name is «firstName» «lastName»''') }}

Классы@Data@SuppressWarnings("all")public class Person { private final String _firstName; public String getFirstName() { this._firstName; } private final String _lastName; public String getLastName() { return this._lastName; } private final int _age; public int getAge() { return this._age; } public void sayHello() { ... } public Person(final String firstName, final String lastName, final int age) { ... } @Override public int hashCode() { ... } @Override public boolean equals(final Object obj) { ... } @Override public String toString() { ... }}

Классыclass Task implements Runnable { @Property val String name @Property var int timeout

new(String name, int timeout) { this._name = name this._timeout = timeout }

new(String name) { this(name, 600) }

override run() { println('''Running task "«name»"''') ... }}

Операторы

Xtend Javaa == b Objects.equals(a, b)a === b a == ba -> b Pair.of(a, b)a ** b Math.pow(a, b)a .. b new IntegerRange(a, b)a ..< b new ExclusiveRange(a, b,

true)a >.. b new ExclusiveRange(a, b,

false)a ?: b if (a != null) a else b

a?.doStuff if (a != null) a.doStuff()

extension-методы

"text".toFirstUpper

extension-методы

"text".toFirstUpper

import org.eclipse.xtext.xbase.lib.StringExtensions;

StringExtensions.toFirstUpper("text");

Стандартные extension-методы

ObjectExtensionsByteExtensionsShortExtensionsIntegerExtensionsLongExtensionsFloatExtensionsBooleanExtensionsDoubleExtensionsCharacterExtension

s

BigIntegerExtensions

BigDecimalExtensions

IterableExtensionsMapExtensionsListExtensions

CollectionExtensions

FunctionExtensionsProcedureExtensionsComparableExtension

s

Внешние extension-методы

import java.io.Fileimport com.google.common.io.Files;

class Main { def static void main(String[] args) { val file = new File('''C:\jdk1.7.0_25\README.html''') val bytes = Files::toByteArray(file) ... }}

Внешние extension-методы

import java.io.Fileimport static extension com.google.common.io.Files.*;

class Main { def static void main(String[] args) { val file = new File('''C:\jdk1.7.0_25\README.html''') val bytes = file.toByteArray ... }}

Локальные extension-методы

class Main { def static void main(String[] args) { val f = 5.factorial println(f) }

def static int factorial(int n) { if (n == 1) 1 else n * factorial(n - 1) }}

Extension providers

class EntityRepository { var extension EntityManager entityManager

def void doSmth() { val person = new Person("John", "Doe") person.persist }}

Lambdasval Comparator<String> c = [a,b | Integer::compare(a.length, b.length)]

Lambdasval Comparator<String> c = [a,b | Integer::compare(a.length, b.length)]

final Comparator<String> _function = new Comparator<String>() { public int compare(final String a, final String b) { int _length = a.length(); int _length_1 = b.length(); int _compare = Integer.compare(_length, _length_1); return _compare; }};

final Comparator<String> c = _function;

Lambdas

val persons = #[new Person("John", "Doe"),new Person("Jane", "Roe"),new Person("David", "McFly")

]

val names = persons.map([p | p.firstName])// John, Jane, David

Lambdas

val persons = #[new Person("John", "Doe"),new Person("Jane", "Roe"),new Person("David", "McFly")

]

val names = persons.map([it.firstName])// John, Jane, David

Lambdas

val persons = #[new Person("John", "Doe"),new Person("Jane", "Roe"),new Person("David", "McFly")

]

val names = persons.map([firstName])// John, Jane, David

Lambdas

val persons = #[new Person("John", "Doe"),new Person("Jane", "Roe"),new Person("David", "McFly")

]

val names = persons.map[firstName]// John, Jane, David

Lambdas

val persons = #[new Person("John", "Doe", true),new Person("Jane", "Roe", false),new Person("David", "McFly", true)

]

val women = persons.filter[female]// Jane Roe

Задача

Найти человека ссамой длинной фамилией

Решение #0

var Person person = null;for (p : persons) { if (person == null || p.lastName.length > person.lastName.length) { person = p }}

Решение #0

var Person person = null;for (p : persons) { if (person == null || p.lastName.length > person.lastName.length) { person = p }}

Решение #1

val person = persons.sortBy[lastName.length].last

Решение #2

import static extension java.util.Collections.* val person = persons.max[ p1, p2 | p1.lastName.length - p2.lastName.length]

Решение #3

val person = persons.reduce[ pWithLongestLastName, p | if (pWithLongestLastName.lastName.length > p.lastName.length) pWithLongestLastName else p]

Решение #4

val person = persons.maxBy[lastName.length]

Multiple dispatch

GameObject

Spaceship Asteroid

Multiple dispatchdef static void main(String[] args) { val GameObject asteroid = new Asteroid val GameObject spaceship = new Spaceship collide(asteroid, spaceship)}

def static void collide(Asteroid x, Asteroid y) { println('астероид сталкивается с астероидом')}def static void collide(Asteroid x, Spaceship y) { println('астероид сталкивается с космическим кораблем')}def static void collide(Spaceship x, Asteroid y) { println('космический корабль сталкивается с астероидом')}def static void collide(Spaceship x, Spaceship y) { println('космический корабль сталкивается с космическим кораблем')}

Multiple dispatchdef static void main(String[] args) { val GameObject asteroid = new Asteroid val GameObject spaceship = new Spaceship collide(asteroid, spaceship) // Ошибка компиляции}

def static void collide(Asteroid x, Asteroid y) { println('астероид сталкивается с астероидом')}def static void collide(Asteroid x, Spaceship y) { println('астероид сталкивается с космическим кораблем')}def static void collide(Spaceship x, Asteroid y) { println('космический корабль сталкивается с астероидом')}def static void collide(Spaceship x, Spaceship y) { println('космический корабль сталкивается с космическим кораблем')}

Multiple dispatchdef static void main(String[] args) { val GameObject asteroid = new Asteroid val GameObject spaceship = new Spaceship collide(asteroid, spaceship) // OK}

def static dispatch void collide(Asteroid x, Asteroid y) { println('астероид сталкивается с астероидом')}def static dispatch void collide(Asteroid x, Spaceship y) { println('астероид сталкивается с космическим кораблем')}def static dispatch void collide(Spaceship x, Asteroid y) { println('космический корабль сталкивается с астероидом')}def static dispatch void collide(Spaceship x, Spaceship y) { println('космический корабль сталкивается с космическим кораблем')}

Multiple dispatchprotected static void _collide(final Asteroid x, final Asteroid y) { InputOutput.<String>println("астероид сталкивается с астероидом");}protected static void _collide(final Asteroid x, final Spaceship y) { InputOutput.<String>println("астероид сталкивается с космическим кораблем");}protected static void _collide(final Spaceship x, final Asteroid y) { InputOutput.<String>println("космический корабль сталкивается с астероидом");}protected static void _collide(final Spaceship x, final Spaceship y) { InputOutput.<String>println("космический корабль сталкивается с космическим кораблем");}

public static void collide(final GameObject x, final GameObject y) { if (x instanceof Asteroid && y instanceof Asteroid) { _collide((Asteroid)x, (Asteroid)y); return; } else if (x instanceof Asteroid && y instanceof Spaceship) { _collide((Asteroid)x, (Spaceship)y); return; } else if (x instanceof Spaceship && y instanceof Asteroid) { _collide((Spaceship)x, (Asteroid)y); return; } else if (x instanceof Spaceship && y instanceof Spaceship) { _collide((Spaceship)x, (Spaceship)y); return; } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object>asList(x, y).toString()); }}

Template expressions

val name = "James"println("Hello " + name + "!")

Template expressions

val name = "James"println('''Hello «name»!''')

Template expressions

val name = "James"println('''Hello «name»!''')

final String name = "James";StringConcatenation _builder = new StringConcatenation();_builder.append("Hello ");_builder.append(name, "");_builder.append("!");InputOutput.<String>println(_builder.toString());

Template expressions

def static html(String text, String image) { ''' <!DOCTYPE html> <html> <body> <p>«text»</p> <img src='«image»' width='«getWidth(image)»' height='«getHeight(image)»'/> </body> </html> '''}

Active annotations

class Tweets { List<String> allTweets = TweetReader::allTweets

...}

Active annotations

class Tweets { @Lazy List<String> allTweets = TweetReader::allTweets

...}

Active annotations@Target(ElementType::FIELD)annotation Lazy {}

Active annotations@Target(ElementType::FIELD)@Active(typeof(LazyProcessor))annotation Lazy {}

Active annotations@Target(ElementType::FIELD)@Active(typeof(LazyProcessor))annotation Lazy {}

class LazyProcessor extends AbstractFieldProcessor { override doTransform(MutableFieldDeclaration field, extension TransformationContext context) { if (field.type.primitive) field.addError("Fields with primitives are not supported by @Lazy") if (field.initializer == null) field.addError("A lazy field must have an initializer.") field.declaringType.addMethod('_init' + field.simpleName) [ visibility = Visibility::PRIVATE returnType = field.type body = field.initializer ] field.declaringType.addMethod('get' + field.simpleName.toFirstUpper) [ returnType = field.type body = [''' if («field.simpleName»==null) «field.simpleName» = _init«field.simpleName»(); return «field.simpleName»; '''] ] }}

Заключение

• Xtend – довольно сырой язык

Заключение

• Xtend – довольно сырой язык– Есть баги– Проблемы с производительностью– Очень маленькое сообщество

Заключение

• Xtend – довольно сырой язык– Есть баги– Проблемы с производительностью– Очень маленькое сообщество

• Неплохая поддержка IDE

Заключение

• Xtend – довольно сырой язык– Есть баги– Проблемы с производительностью– Очень маленькое сообщество

• Неплохая поддержка IDE• Язык не является убийцей Java, он является

убийцей её синтаксиса

Recommended