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

Xtend

Embed Size (px)

DESCRIPTION

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

Citation preview

Page 1: Xtend

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

Page 2: Xtend

Xtend

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

Page 3: Xtend

Xtend

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

Page 4: Xtend

Xtend

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

Page 5: Xtend

Xtend

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

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

Page 6: Xtend

Xtend

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

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

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

Page 7: Xtend

Языки JVM

Yeti

Erjang

Frege

Page 8: Xtend

Языки JVM

Yeti

Erjang

Frege

Page 9: Xtend

Языки JVM

Yeti

Frege

Page 10: Xtend

Языки JVM

Page 11: Xtend

Языки JVM

Page 12: Xtend

Языки JVM

Page 13: Xtend

Кол-во вопросов на 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

Page 14: Xtend

Опрос

Page 15: Xtend

No ; and ()

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

Page 16: Xtend

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); }}

Page 17: Xtend

val, var and type inference

val n = 5

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

str = ...}

Page 18: Xtend

val, var and type inference

val int n = 5

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

str = ...}

Page 19: Xtend

Type inference

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

println(list)

Page 20: Xtend

Type inference

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

println(list)

Какой тип у ArrayList?

Page 21: Xtend

Type inference

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

println(list)

Page 22: Xtend

Type inference

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

println(list)

Page 23: Xtend

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

println(data)

data}

Page 24: Xtend

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 }}

Page 25: Xtend

Классы

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

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

Page 26: Xtend

Классы@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() { ... }}

Page 27: Xtend

Классы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»"''') ... }}

Page 28: Xtend

Операторы

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()

Page 29: Xtend

extension-методы

"text".toFirstUpper

Page 30: Xtend

extension-методы

"text".toFirstUpper

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

StringExtensions.toFirstUpper("text");

Page 31: Xtend

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

ObjectExtensionsByteExtensionsShortExtensionsIntegerExtensionsLongExtensionsFloatExtensionsBooleanExtensionsDoubleExtensionsCharacterExtension

s

BigIntegerExtensions

BigDecimalExtensions

IterableExtensionsMapExtensionsListExtensions

CollectionExtensions

FunctionExtensionsProcedureExtensionsComparableExtension

s

Page 32: Xtend

Внешние 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) ... }}

Page 33: Xtend

Внешние 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 ... }}

Page 34: Xtend

Локальные 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) }}

Page 35: Xtend

Extension providers

class EntityRepository { var extension EntityManager entityManager

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

Page 36: Xtend

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

Page 37: Xtend

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;

Page 38: Xtend

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

Page 39: Xtend

Lambdas

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

]

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

Page 40: Xtend

Lambdas

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

]

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

Page 41: Xtend

Lambdas

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

]

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

Page 42: Xtend

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

Page 43: Xtend

Задача

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

Page 44: Xtend

Решение #0

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

Page 45: Xtend

Решение #0

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

Page 46: Xtend

Решение #1

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

Page 47: Xtend

Решение #2

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

Page 48: Xtend

Решение #3

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

Page 49: Xtend

Решение #4

val person = persons.maxBy[lastName.length]

Page 50: Xtend

Multiple dispatch

GameObject

Spaceship Asteroid

Page 51: Xtend

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('космический корабль сталкивается с космическим кораблем')}

Page 52: Xtend

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('космический корабль сталкивается с космическим кораблем')}

Page 53: Xtend

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('космический корабль сталкивается с космическим кораблем')}

Page 54: Xtend

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()); }}

Page 55: Xtend

Template expressions

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

Page 56: Xtend

Template expressions

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

Page 57: Xtend

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());

Page 58: Xtend

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> '''}

Page 59: Xtend

Active annotations

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

...}

Page 60: Xtend

Active annotations

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

...}

Page 61: Xtend

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

Page 62: Xtend

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

Page 63: Xtend

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»; '''] ] }}

Page 64: Xtend

Заключение

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

Page 65: Xtend

Заключение

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

Page 66: Xtend

Заключение

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

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

Page 67: Xtend

Заключение

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

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

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