SlideShare uma empresa Scribd logo
1 de 32
Baixar para ler offline
+

Дмитрий Стропалов, Александр Михальчук
If I were to pick a language to use today other 
                     than Java, it would be Scala
                                    James Gosling

I can honestly say if someone had shown me the 
      Programming in Scala book by by Martin 
Odersky, Lex Spoon & Bill Venners back in 2003 
        I’d probably have never created Groovy
                                   James Strachan
возникновение


• Разработан  в  2001­2004  годах  (представлен  в  2004    г.)  в 
  Лаборатории       методов      программирования           EPFL 
  (Федеральная      политехническая      школа       Лозанны, 
  Швейцария)  под  руководством  Мартина  Одерски (Martin 
  Odersky) 
• Большое  влияние  оказали  исследовательские  работы  в 
  области разработки (компонентного) ПО, ЯП
• Попытка  разработки  языка,  который             бы    хорошо 
  масштабировался (SCAlable LAnguage)
• Унификация         объектно­ориентированного             и 
  функционального  подходов  и  предоставление  их  в  языке 
  со  статической  типизацией.  Расширенные  механизмы 
  абстракции, композиции и декомпозиции
• Хорошая  интеграция  с  существующими  платформами  и 
  библиотеками — изначальная ориентация на совместную 
  работу с Java и .NET
«академический» язык


• LinkedIn  –  фреймфорк  “Norbert”  для  построения 
  асинхронных,     кластерных,      высоконагруженных 
  приложений. Представление социального графа                 
• EDF – крупнейшая во Франции энергетическая компания
• Twitter – главная очередь сообщений (message queue)
• Novell  –  сервис  “Vibe  Cloud”,  предоставляющий 
  корпоративную  закрытую  и  защищенную  платформу  для 
  совместной работы
• The  Guardian  –  API  для  “Open  Platform”,  предоставление 
  доступа к медийному архиву агенства
• Xerox – различное ПО, включая и клиентское
• FourSquare – полностью все предоставляемые сервисы
• Sony – система управления хранением данных
• Siemes (+ SAP) – корпоративная система сообщений
• …  
основные концепции


• Бесшовная интеграция с Java­кодом (C#/.NET)
• Единообразная  объектная  модель  –  любое  значение 
  является объектом, любая операция – вызов метода
• Функциональный язык – функции являются полноправными 
  значениями. Каждая функция возвращает значение
• Механизмы абстракций как для типов, так и для значений
• Использование  «примесей»  (mixin,  trait)  для  композиции 
  классов
• Сравнение с образцом (pattern matching)
• Естественная обработка документов XML
• Выведение типов
• Неизменяемые (immutable types) типы
• Ленивые (lazy) вычисления
hello world!


Вариант I:
   object Application {
       def main(args: Array[String]): Unit = {
         for (arg <­ args) {
              if (arg.startsWith("­"))
                 println(arg)
         }
       }
   }
hello world!


Вариант I:
   object Application {
       def main(args: Array[String]): Unit = {
         for (arg <­ args) {
              if (arg.startsWith("­"))
                 println(arg)
         }
       }
   }

Вариант II:
       def main(args: Array[String]): Unit = {
         for (arg <­ args; if arg.startsWith("­"))
            println(arg)
       }
hello world!


Вариант I:
   object Application {
       def main(args: Array[String]): Unit = {
         for (arg <­ args) {
              if (arg.startsWith("­"))
                 println(arg)
         }
       }
   }

Вариант II:
       def main(args: Array[String]): Unit = {
         for (arg <­ args; if arg.startsWith("­"))
            println(arg)
       }

Вариант III:
      def main(args: Array[String]): Unit = {
             args.withFilter(_.startsWith("­")).map(println)
      }
значения и переменные


          val a: Int = 5
        val b = {
            println("Init b")
            10
        }
        var c = 15
        lazy val d = {
            println("Init d")
            a + c
        }

        println("a:%d b:%d c:%d".format(a, b, c))
        c = 20
        println("c:%d d:%d".format(c, d))
        println("d:" + d)

>>>     Init b
        a:5 b:10 c:15
        Init d
        c:20 d:25
        d:25
классы и объекты


       class Parent(value: String) {
          val classValue = value
       }

       class A1 {
          val a: Int = 0
          private var b = 0
          def getB = b
       }

       object A1 extends Parent("Object A1: ") {
          def setA(obj: A1) { obj.b = 5 }
       }

       object Application extends Application {
          val obj = new A1
          A1.setA(obj)
          println(A1.classValue + obj.getB)
       } 
        
>>>    Object A1: 5
        
трейты (traits)


       trait Role {
          def getRole: Int
          def isAdmin = if (getRole == 0) true else false
       }

       trait Info {
          def getInfo: String
          def setInfo(info: String)
       }

       class User(role: Int) extends Role with Info {
          val userRole = role
          var userInfo: String = ""
          def getRole = userRole
          def getInfo = userInfo
          def setInfo(info: String) { 
              userInfo = info 
          }
       }              
анонимные функции


       object Application extends Application {
          val hello = () => "Hello, anonymous"
          val foo = (x: String) => x.split(':').mkString(", ")
          def bar(s: String, f: String => String) = {
              f(s)
          }

           println(hello)
           println(hello())
           println(foo("value1:value2:value3:value4"))
           println(bar("John:Mike:Ann", foo))
       }

>>>    <function0>
       Hello, anonymous
       value1, value2, value3, value4
       John, Mike, Ann
        
карринг


       def filter(xs: List[Int], p: Int => Boolean): List[Int] =
          if (xs.isEmpty) Nil
          else if (p(xs.head)) xs.head :: filter(xs.tail, p)
          else filter(xs.tail, p)

       def modN(n: Int)(x: Int) = ((x % n) == 0)

       val list = (1 to 10).toList
       println(filter(list, modN(2)))
       println(filter(list, modN(3))) 
        

>>>    List(2, 4, 6, 8, 10)
       List(3, 6, 9)
        
xml


       val xml =
          <depot>
              <item name="item 1">
                 <part name="part 1"/>
                 <part name="part 2"/>
                 <item>inner item</item>
              </item>
              <item name="item 2"></item>
              <label type="title">Depot title</label>
          </depot> 
        
       xml  "item"
       xml  "item"
       xml  "@type"
        
xml


       val ptype = "box"
       val title = "Examples"
       val item = <item type={ ptype }>{ title }</item>

       val items =
         <items>
             {for (index <­ (0 to 3).toList)
                 yield <item>{ index }</item>}
         </items>

       println(item)
       println(items)

>>>    <item type="box">Examples</item>
       <items>
          <item>0</item>
          <item>1</item>
          <item>2</item>
          <item>3</item>
       </items>
сравнение с образцом


       def matcher(x: Any) = {
         x match {
            case 1 => println("Integer value 1")
            case y: Int => println("Integer value: " + y)
            case <e>{ tagValue }</e> => 
                           println("XML Tag value: " + tagValue)
            case _ => println("Something else: " + x)
         }
       }

       matcher(1)
       matcher(10)
       matcher(<e>Lorem ipsum</e>)
       matcher("simple string")

>>>    Integer value 1
       Integer value: 10
       XML Tag value: Lorem ipsum
       Something else: simple string
магический implicit


       implicit def double2int(x: Double) = {
          println("converting double to int ...")
         if (x < 10) 0 else x.toInt
       }
       val i: Int = 3.5
       println(i)

>>>    converting double to int ...
       0


       implicit val a: Int = 10
       implicit val b: Double = 1.5
       def foo(implicit a: Int, b: Double) = {
           println("%d, %f".format(a, b))
       }
       foo

>>>    10, 1.500000
The first rule of Lift is:                                              
                         It's easier than you think.

  I think the most important feature we have in 
                 Lift is the community around it
(committers and non­committers). I have joined 
              the mailing list just a few months
       ago and I am impressed with how willing 
                  everyone is to help each other.
общая информация


• Разработка  начата  в  2007  году,  сейчас  достигнута 
  версия 2.2. Главный разработчик — Девид Поллак (David 
  Pollak). Рабочее название было “Scala on Sails” 
• Разрабатывается  с  целью  объединить  лучшие  идеи  и 
  концепции  из  существующих  web­фреймворков  (Java­
  фреймворки, RoR)
• Концентрация на бизнес­логике приложения
• Простая и эффективная система безопасности
• Использование  преимуществ  Scala  как  базового  языка 
  (контроль   типов,   встроенная     обработка      XML, 
  функциональные элементы)
• View­First предпочтительнее MVC­модели
• Изначальная поддержка AJAX и Comet
• Используется  в  таких  компаниях,  как  Nowell,  SAP, 
  Innovation Games, Foursquare, Untyped и другими
сообщество


• Домашняя страница: http://liftweb.net/
• Google Groups (2500 участников): http://groups.google.com/group/liftweb
• Открытый исходный код на GitHub: 
  http://github.com/dpp/liftweb/tree/master
• Wiki и треккер на Assembla: http://www.assembla.com/wiki/show/liftweb/
• Бесплатные книги:
  Exploring Lift: http://exploring.liftweb.net/
  Simply Lift: http://stable.simply.liftweb.net/
• Дружелюбное комьюнити и Поллак
быстрый старт


• Генерация приложения Scala 2.8.1 + Lift 2.2:
 mvn archetype:generate 
 ­DarchetypeGroupId=net.liftweb 
 ­DarchetypeArtifactId=lift­archetype­basic_2.8.1 
 ­DarchetypeVersion=2.2 
 ­DarchetypeRepository=http://scala­tools.org/repo­releases 
 ­DremoteRepositories=http://scala­tools.org/repo­releases 
 ­DgroupId=ua.dn.cnc 
 ­DartifactId=lift_demo 
 ­Dversion=1.0


• Запуск сервера:
 mvn jetty:run
структура проекта


 Структура каталога нового проекта:
• project – Simple Build Tool (SBT) конфигурация
• src/main/resources – ресурсы проекта
• src/main/scala – исходный код на Scala
• ua.dn.cnc.Boot – конфигурация Lift приложения
• ua.dn.cnc.lib.DependencyFactory  –  Dependency 
  Injection
• ua.dn.cnc.model.User – сущность User
• ua.dn.cnc.snippet.HelloWorld – Hello World сниппет
• src/main/webapp – web ресурсы (шаблоны, html, 
  css, js)
• src/main/test ­ исходный код тестов
• pom.xml – Apache Maven конфигурация
mapper orm


object News extends News with LongKeyedMetaMapper[News] {
    override def dbIndexes = 
       UniqueIndex(title) :: super.dbIndexes
}
class News extends LongKeyedMapper[News] with IdPK {
    def getSingleton = News

    object title extends MappedString(this, 255) {
        override def dbNotNull_? = true
    }
    object text extends MappedString(this, 1200) {
        override def dbNotNull_? = true
    }
    object publish extends MappedBoolean(this) {
        override def dbNotNull_? = true
        override def defaultValue: Boolean = true
    }
    object date extends MappedDate(this) {
        override def dbNotNull_? = true
    }
}
mapper orm

Создание записи:
   val n = News.create
   n.title("Lorem ipsum")
   …
   n.save

Удаление записи:
   n.delete_!

Все записи:
   val n = News.findAll

Записи по условию:
   val n = News.findAll(By(News.publish, true),                 
                        OrderBy(News.date, Descending),
                        StartAt(0), MaxRows(10))

Записи по SQL­запросу:
   val n = News.findAllByInsecureSql("select * from news " +
             "where publish = 1 order by(date_c)",
             IHaveValidatedThisSQL("dba", "2011­01­01"))
menu

Boot.scala:

    import net.liftweb.http.LiftRules
    import net.liftweb.sitemap.Loc
    import net.liftweb.sitemap.Loc.Hidden
    import net.liftweb.sitemap.Loc.strLstToLink
    import net.liftweb.sitemap.Menu
    import net.liftweb.sitemap.SiteMap
    ...
    def boot {
        ...
        val myLoc = Loc("HomePage", "index" :: Nil, "Home Page", 
            Hidden)
        val myMenu = Menu(myLoc)
        val allMenus = myMenu :: User.sitemap
        val mySiteMap = SiteMap(allMenus: _*)
        LiftRules.setSiteMap(mySiteMap)
        ...
menu

Loc:
    Loc(theName:"Home", theLink:new Link(List("index")), 
       theText:"Home Page")
    Loc("About", "info" :: "about" :: Nil, "About", Hidden)
    Loc("HomePage", "index" :: Nil, "Home Page", Test((req) => 
       req.isIE6))
    Loc("Static", Link(List("static"), true, "/static/index"), 
       "Static Content")
Menu:
    val myMenu = Menu(Loc("About", "about" :: Nil, "About", 
       Hidden))
    val helpMenu = Menu(myHelpMenuLoc, myUserHelpMenu, 
       myTechnicalHelpMenu)
    val allMenus = myMenu :: User.menus

SiteMap:
    LiftRules.setSiteMap(SiteMap(allMenus: _*))

HTML­вывод:
   <lift:Menu.builder /> или <div class="lift:Menu.builder" />
url rewriting

bootstrap.liftweb.Boot.boot:

    LiftRules.rewrite.prepend(NamedPF("ArticleRewrite") {
       case RewriteRequest(
       ParsePath("article" :: id :: action :: _, _, _, _)
           , _, _) =>
       RewriteResponse(
           "article" :: action :: Nil, Map("id" ­> id))
    })


    /article/1/edit ­> /article/edit?id=1
шаблоны

      default.html                        index.html
                                   <lift:surround with="default">
<html>
 <head>                                  <lift:bind-at name="controls">
  …                                            <head>
 </head>                                            <script src="…"/>
                                               </head>
 <body>                                        <div class="controls">
  <div>                                             …
   …                                           </div>
   <lift:bind name="controls" />         </lift:bind-at>
  </div>
                                         <lift:bind-at name="content">
  …                                            <div class="content">
                                                    …
  <lift:bind name="content" />                 </div>
                                         </lift:bind-at>
  …
 </body>                           </lift:surround>
</html>
snippets


 …                               …
  <ul>                            <ul>
    <lift:Test.show>                <li>Foo: Bar</li>
        <li><e:item/></li>          <li>Fizz: Buzz</li>
    </lift:Test.show>               <li>Some title: and some text</li>
  </ul>                           </ul>
 …                               …


class Test {
   def show(in: NodeSeq): NodeSeq = {
       TestModel.findAll().flatMap(item =>
          bind("e", in, "item" ­> Text(
                    "%s: %s".format(item.title, item.text)
               ))
          )
   }
}
формы

Автоматическая генерация:
   Model.toForm(Full("Save"), { _.save })

Snippet:
    private var newKeyword = ""

   def keywordsForm(in: NodeSeq): NodeSeq = {
        bind("entry", in,
            "addNewKeyword" ­> SHtml.text("", newKeyword = _, 
                                           "maxlength" ­> "50"),
            "submitNewKeyword" ­> SHtml.submit("Добавить", 
                                              addNewKeyword))
   }

   private def addNewKeyword() { …
        val kw =                  <lift:clazz.keywordsForm form="POST">
          KeywordsModel.create       <entry:addNewKeyword />
        kw.keyword(newKeyword)       <entry:submitNewKeyword />
        kw.save                   </lift:clazz.keywordsForm>
   }                             …
ссылки


• Обзор языка программирования Scala
• Статьи на Habrahabr
• Programming Scala
• Scala Reference Manuals
• Scala Style Guide
• Exploring Lift
• Lift Wiki
Спасибо за внимание и EOF

Mais conteúdo relacionado

Mais procurados

9. java lecture library
9. java lecture library9. java lecture library
9. java lecture library
MERA_school
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
MERA_school
 

Mais procurados (14)

Лекция 1. Начало.
Лекция 1. Начало.Лекция 1. Начало.
Лекция 1. Начало.
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 
Метапрограммирование за гранью приличия
Метапрограммирование за гранью приличияМетапрограммирование за гранью приличия
Метапрограммирование за гранью приличия
 
Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.Лекция 5. Встроенные коллекции и модуль collections.
Лекция 5. Встроенные коллекции и модуль collections.
 
Scala - my path
Scala - my pathScala - my path
Scala - my path
 
9. java lecture library
9. java lecture library9. java lecture library
9. java lecture library
 
Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.Лекция 12. Быстрее, Python, ещё быстрее.
Лекция 12. Быстрее, Python, ещё быстрее.
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
 
Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование Декораторы в Python и их практическое использование
Декораторы в Python и их практическое использование
 
Лекция 8. Итераторы, генераторы и модуль itertools.
 Лекция 8. Итераторы, генераторы и модуль itertools. Лекция 8. Итераторы, генераторы и модуль itertools.
Лекция 8. Итераторы, генераторы и модуль itertools.
 
Профилирование и отладка Django
Профилирование и отладка DjangoПрофилирование и отладка Django
Профилирование и отладка Django
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.Лекция 2. Всё, что вы хотели знать о функциях в Python.
Лекция 2. Всё, что вы хотели знать о функциях в Python.
 
Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.Лекция 3. Декораторы и модуль functools.
Лекция 3. Декораторы и модуль functools.
 

Destaque

презентация12
презентация12презентация12
презентация12
MartiniAnn
 
Drd700
Drd700Drd700
Drd700
ciperi
 
F acebook:twitter
F acebook:twitterF acebook:twitter
F acebook:twitter
Gray122
 
Solution to assignment 1
Solution to assignment 1Solution to assignment 1
Solution to assignment 1
Liu Liu
 

Destaque (8)

презентация12
презентация12презентация12
презентация12
 
The Darwish Resistance: The Clash Between Somali Clanship And State System
The Darwish Resistance: The Clash Between Somali Clanship And State SystemThe Darwish Resistance: The Clash Between Somali Clanship And State System
The Darwish Resistance: The Clash Between Somali Clanship And State System
 
Drd700
Drd700Drd700
Drd700
 
11e2d ass1
11e2d ass111e2d ass1
11e2d ass1
 
F acebook:twitter
F acebook:twitterF acebook:twitter
F acebook:twitter
 
Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...
Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...
Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...
 
Solution to assignment 1
Solution to assignment 1Solution to assignment 1
Solution to assignment 1
 
Devoxx 2010 | LAB : ReST in Java
Devoxx 2010 | LAB : ReST in JavaDevoxx 2010 | LAB : ReST in Java
Devoxx 2010 | LAB : ReST in Java
 

Semelhante a Scala and LiftWeb presentation (Russian)

Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
ScalaNsk
 
Web осень 2012 лекция 9
Web осень 2012 лекция 9Web осень 2012 лекция 9
Web осень 2012 лекция 9
Technopark
 
20100425 model based_testing_kuliamin_lectures01-03
20100425 model based_testing_kuliamin_lectures01-0320100425 model based_testing_kuliamin_lectures01-03
20100425 model based_testing_kuliamin_lectures01-03
Computer Science Club
 

Semelhante a Scala and LiftWeb presentation (Russian) (20)

Scala for android
Scala for androidScala for android
Scala for android
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
 
Зачем нужна Scala?
Зачем нужна Scala?Зачем нужна Scala?
Зачем нужна Scala?
 
Scala on android
Scala on androidScala on android
Scala on android
 
Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)Scala для всех (РИФ 2015)
Scala для всех (РИФ 2015)
 
msumobi2. Лекция 1
msumobi2. Лекция 1msumobi2. Лекция 1
msumobi2. Лекция 1
 
Why Every Language Needs Its Underscore
Why Every Language Needs Its UnderscoreWhy Every Language Needs Its Underscore
Why Every Language Needs Its Underscore
 
Язык программирования C#
Язык программирования C#Язык программирования C#
Язык программирования C#
 
Александр Щепановский «Почему каждому языку нужен свой _»
Александр Щепановский «Почему каждому языку нужен свой _»Александр Щепановский «Почему каждому языку нужен свой _»
Александр Щепановский «Почему каждому языку нужен свой _»
 
Javascript 1
Javascript 1Javascript 1
Javascript 1
 
C sharp deep dive
C sharp deep diveC sharp deep dive
C sharp deep dive
 
C# Deep Dive
C# Deep DiveC# Deep Dive
C# Deep Dive
 
Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)Clojure: Lisp for the modern world (русская версия)
Clojure: Lisp for the modern world (русская версия)
 
Scala #3
Scala #3Scala #3
Scala #3
 
Bytecode
BytecodeBytecode
Bytecode
 
Web осень 2012 лекция 9
Web осень 2012 лекция 9Web осень 2012 лекция 9
Web осень 2012 лекция 9
 
20100425 model based_testing_kuliamin_lectures01-03
20100425 model based_testing_kuliamin_lectures01-0320100425 model based_testing_kuliamin_lectures01-03
20100425 model based_testing_kuliamin_lectures01-03
 
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
Denys Samoylenko ''JS learning lifehacks: common programmer's mistake''
 
Scala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application DevelopmentScala, SBT & Play! for Rapid Application Development
Scala, SBT & Play! for Rapid Application Development
 
Java осень 2014 занятие 3
Java осень 2014 занятие 3Java осень 2014 занятие 3
Java осень 2014 занятие 3
 

Scala and LiftWeb presentation (Russian)

  • 2. If I were to pick a language to use today other  than Java, it would be Scala James Gosling I can honestly say if someone had shown me the  Programming in Scala book by by Martin  Odersky, Lex Spoon & Bill Venners back in 2003  I’d probably have never created Groovy James Strachan
  • 3. возникновение • Разработан  в  2001­2004  годах  (представлен  в  2004    г.)  в  Лаборатории  методов  программирования  EPFL  (Федеральная  политехническая  школа  Лозанны,  Швейцария)  под  руководством  Мартина  Одерски (Martin  Odersky)  • Большое  влияние  оказали  исследовательские  работы  в  области разработки (компонентного) ПО, ЯП • Попытка  разработки  языка,  который  бы  хорошо  масштабировался (SCAlable LAnguage) • Унификация  объектно­ориентированного  и  функционального  подходов  и  предоставление  их  в  языке  со  статической  типизацией.  Расширенные  механизмы  абстракции, композиции и декомпозиции • Хорошая  интеграция  с  существующими  платформами  и  библиотеками — изначальная ориентация на совместную  работу с Java и .NET
  • 4. «академический» язык • LinkedIn  –  фреймфорк  “Norbert”  для  построения  асинхронных,  кластерных,  высоконагруженных  приложений. Представление социального графа                  • EDF – крупнейшая во Франции энергетическая компания • Twitter – главная очередь сообщений (message queue) • Novell  –  сервис  “Vibe  Cloud”,  предоставляющий  корпоративную  закрытую  и  защищенную  платформу  для  совместной работы • The  Guardian  –  API  для  “Open  Platform”,  предоставление  доступа к медийному архиву агенства • Xerox – различное ПО, включая и клиентское • FourSquare – полностью все предоставляемые сервисы • Sony – система управления хранением данных • Siemes (+ SAP) – корпоративная система сообщений • …  
  • 5. основные концепции • Бесшовная интеграция с Java­кодом (C#/.NET) • Единообразная  объектная  модель  –  любое  значение  является объектом, любая операция – вызов метода • Функциональный язык – функции являются полноправными  значениями. Каждая функция возвращает значение • Механизмы абстракций как для типов, так и для значений • Использование  «примесей»  (mixin,  trait)  для  композиции  классов • Сравнение с образцом (pattern matching) • Естественная обработка документов XML • Выведение типов • Неизменяемые (immutable types) типы • Ленивые (lazy) вычисления
  • 6. hello world! Вариант I: object Application {      def main(args: Array[String]): Unit = {          for (arg <­ args) {           if (arg.startsWith("­"))              println(arg)          }      } }
  • 7. hello world! Вариант I: object Application {      def main(args: Array[String]): Unit = {          for (arg <­ args) {           if (arg.startsWith("­"))              println(arg)          }      } } Вариант II:      def main(args: Array[String]): Unit = {          for (arg <­ args; if arg.startsWith("­"))             println(arg)      }
  • 8. hello world! Вариант I: object Application {      def main(args: Array[String]): Unit = {          for (arg <­ args) {           if (arg.startsWith("­"))              println(arg)          }      } } Вариант II:      def main(args: Array[String]): Unit = {          for (arg <­ args; if arg.startsWith("­"))             println(arg)      } Вариант III:      def main(args: Array[String]): Unit = { args.withFilter(_.startsWith("­")).map(println)      }
  • 9. значения и переменные    val a: Int = 5         val b = {             println("Init b")             10         }         var c = 15         lazy val d = {             println("Init d")             a + c         }         println("a:%d b:%d c:%d".format(a, b, c))         c = 20         println("c:%d d:%d".format(c, d))         println("d:" + d) >>>   Init b  a:5 b:10 c:15  Init d  c:20 d:25  d:25
  • 10. классы и объекты class Parent(value: String) {      val classValue = value } class A1 {      val a: Int = 0      private var b = 0      def getB = b } object A1 extends Parent("Object A1: ") {      def setA(obj: A1) { obj.b = 5 } } object Application extends Application {      val obj = new A1      A1.setA(obj)      println(A1.classValue + obj.getB) }           >>>  Object A1: 5  
  • 11. трейты (traits) trait Role {      def getRole: Int      def isAdmin = if (getRole == 0) true else false } trait Info {      def getInfo: String      def setInfo(info: String) } class User(role: Int) extends Role with Info {      val userRole = role      var userInfo: String = ""      def getRole = userRole      def getInfo = userInfo      def setInfo(info: String) {  userInfo = info  } }  
  • 12. анонимные функции object Application extends Application {      val hello = () => "Hello, anonymous"      val foo = (x: String) => x.split(':').mkString(", ")      def bar(s: String, f: String => String) = {          f(s)      }      println(hello) println(hello())      println(foo("value1:value2:value3:value4"))      println(bar("John:Mike:Ann", foo)) } >>>  <function0> Hello, anonymous value1, value2, value3, value4 John, Mike, Ann  
  • 13. карринг def filter(xs: List[Int], p: Int => Boolean): List[Int] = if (xs.isEmpty) Nil else if (p(xs.head)) xs.head :: filter(xs.tail, p) else filter(xs.tail, p) def modN(n: Int)(x: Int) = ((x % n) == 0) val list = (1 to 10).toList println(filter(list, modN(2))) println(filter(list, modN(3)))           >>>  List(2, 4, 6, 8, 10) List(3, 6, 9)  
  • 14. xml val xml =      <depot>          <item name="item 1">              <part name="part 1"/>              <part name="part 2"/>              <item>inner item</item>          </item>          <item name="item 2"></item>          <label type="title">Depot title</label>      </depot>           xml  "item"      xml  "item"      xml  "@type"  
  • 15. xml val ptype = "box"      val title = "Examples"      val item = <item type={ ptype }>{ title }</item>      val items =          <items>              {for (index <­ (0 to 3).toList)                  yield <item>{ index }</item>}          </items>      println(item)      println(items) >>> <item type="box">Examples</item> <items>         <item>0</item> <item>1</item> <item>2</item> <item>3</item>        </items>
  • 16. сравнение с образцом def matcher(x: Any) = {          x match {             case 1 => println("Integer value 1")             case y: Int => println("Integer value: " + y)             case <e>{ tagValue }</e> =>  println("XML Tag value: " + tagValue)             case _ => println("Something else: " + x)          }      }      matcher(1)      matcher(10)      matcher(<e>Lorem ipsum</e>)      matcher("simple string") >>> Integer value 1 Integer value: 10 XML Tag value: Lorem ipsum Something else: simple string
  • 17. магический implicit implicit def double2int(x: Double) = {         println("converting double to int ...")          if (x < 10) 0 else x.toInt      }      val i: Int = 3.5      println(i) >>> converting double to int ... 0 implicit val a: Int = 10      implicit val b: Double = 1.5      def foo(implicit a: Int, b: Double) = { println("%d, %f".format(a, b)) }      foo >>> 10, 1.500000
  • 18. The first rule of Lift is:                                               It's easier than you think. I think the most important feature we have in  Lift is the community around it (committers and non­committers). I have joined  the mailing list just a few months ago and I am impressed with how willing  everyone is to help each other.
  • 19. общая информация • Разработка  начата  в  2007  году,  сейчас  достигнута  версия 2.2. Главный разработчик — Девид Поллак (David  Pollak). Рабочее название было “Scala on Sails”  • Разрабатывается  с  целью  объединить  лучшие  идеи  и  концепции  из  существующих  web­фреймворков  (Java­ фреймворки, RoR) • Концентрация на бизнес­логике приложения • Простая и эффективная система безопасности • Использование  преимуществ  Scala  как  базового  языка  (контроль  типов,  встроенная  обработка  XML,  функциональные элементы) • View­First предпочтительнее MVC­модели • Изначальная поддержка AJAX и Comet • Используется  в  таких  компаниях,  как  Nowell,  SAP,  Innovation Games, Foursquare, Untyped и другими
  • 20. сообщество • Домашняя страница: http://liftweb.net/ • Google Groups (2500 участников): http://groups.google.com/group/liftweb • Открытый исходный код на GitHub:  http://github.com/dpp/liftweb/tree/master • Wiki и треккер на Assembla: http://www.assembla.com/wiki/show/liftweb/ • Бесплатные книги:  Exploring Lift: http://exploring.liftweb.net/  Simply Lift: http://stable.simply.liftweb.net/ • Дружелюбное комьюнити и Поллак
  • 21. быстрый старт • Генерация приложения Scala 2.8.1 + Lift 2.2: mvn archetype:generate  ­DarchetypeGroupId=net.liftweb  ­DarchetypeArtifactId=lift­archetype­basic_2.8.1  ­DarchetypeVersion=2.2  ­DarchetypeRepository=http://scala­tools.org/repo­releases  ­DremoteRepositories=http://scala­tools.org/repo­releases  ­DgroupId=ua.dn.cnc  ­DartifactId=lift_demo  ­Dversion=1.0 • Запуск сервера: mvn jetty:run
  • 22. структура проекта Структура каталога нового проекта: • project – Simple Build Tool (SBT) конфигурация • src/main/resources – ресурсы проекта • src/main/scala – исходный код на Scala • ua.dn.cnc.Boot – конфигурация Lift приложения • ua.dn.cnc.lib.DependencyFactory  –  Dependency  Injection • ua.dn.cnc.model.User – сущность User • ua.dn.cnc.snippet.HelloWorld – Hello World сниппет • src/main/webapp – web ресурсы (шаблоны, html,  css, js) • src/main/test ­ исходный код тестов • pom.xml – Apache Maven конфигурация
  • 23. mapper orm object News extends News with LongKeyedMetaMapper[News] {     override def dbIndexes =  UniqueIndex(title) :: super.dbIndexes } class News extends LongKeyedMapper[News] with IdPK {     def getSingleton = News     object title extends MappedString(this, 255) {         override def dbNotNull_? = true     }     object text extends MappedString(this, 1200) {         override def dbNotNull_? = true     }     object publish extends MappedBoolean(this) {         override def dbNotNull_? = true         override def defaultValue: Boolean = true     }     object date extends MappedDate(this) {         override def dbNotNull_? = true     } }
  • 24. mapper orm Создание записи: val n = News.create n.title("Lorem ipsum") … n.save Удаление записи: n.delete_! Все записи: val n = News.findAll Записи по условию:    val n = News.findAll(By(News.publish, true),                                          OrderBy(News.date, Descending),                         StartAt(0), MaxRows(10)) Записи по SQL­запросу:    val n = News.findAllByInsecureSql("select * from news " +              "where publish = 1 order by(date_c)",              IHaveValidatedThisSQL("dba", "2011­01­01"))
  • 25. menu Boot.scala: import net.liftweb.http.LiftRules import net.liftweb.sitemap.Loc import net.liftweb.sitemap.Loc.Hidden import net.liftweb.sitemap.Loc.strLstToLink import net.liftweb.sitemap.Menu import net.liftweb.sitemap.SiteMap ... def boot { ... val myLoc = Loc("HomePage", "index" :: Nil, "Home Page",  Hidden) val myMenu = Menu(myLoc) val allMenus = myMenu :: User.sitemap val mySiteMap = SiteMap(allMenus: _*) LiftRules.setSiteMap(mySiteMap) ...
  • 26. menu Loc: Loc(theName:"Home", theLink:new Link(List("index")),  theText:"Home Page") Loc("About", "info" :: "about" :: Nil, "About", Hidden) Loc("HomePage", "index" :: Nil, "Home Page", Test((req) =>  req.isIE6)) Loc("Static", Link(List("static"), true, "/static/index"),  "Static Content") Menu: val myMenu = Menu(Loc("About", "about" :: Nil, "About",  Hidden)) val helpMenu = Menu(myHelpMenuLoc, myUserHelpMenu,  myTechnicalHelpMenu) val allMenus = myMenu :: User.menus SiteMap: LiftRules.setSiteMap(SiteMap(allMenus: _*)) HTML­вывод: <lift:Menu.builder /> или <div class="lift:Menu.builder" />
  • 27. url rewriting bootstrap.liftweb.Boot.boot: LiftRules.rewrite.prepend(NamedPF("ArticleRewrite") { case RewriteRequest( ParsePath("article" :: id :: action :: _, _, _, _) , _, _) => RewriteResponse( "article" :: action :: Nil, Map("id" ­> id)) }) /article/1/edit ­> /article/edit?id=1
  • 28. шаблоны default.html index.html <lift:surround with="default"> <html> <head> <lift:bind-at name="controls"> … <head> </head> <script src="…"/> </head> <body> <div class="controls"> <div> … … </div> <lift:bind name="controls" /> </lift:bind-at> </div> <lift:bind-at name="content"> … <div class="content"> … <lift:bind name="content" /> </div> </lift:bind-at> … </body> </lift:surround> </html>
  • 29. snippets … … <ul> <ul> <lift:Test.show> <li>Foo: Bar</li> <li><e:item/></li> <li>Fizz: Buzz</li> </lift:Test.show> <li>Some title: and some text</li> </ul> </ul> … … class Test { def show(in: NodeSeq): NodeSeq = { TestModel.findAll().flatMap(item =>           bind("e", in, "item" ­> Text(                     "%s: %s".format(item.title, item.text)                ))           ) } }
  • 30. формы Автоматическая генерация: Model.toForm(Full("Save"), { _.save }) Snippet: private var newKeyword = "" def keywordsForm(in: NodeSeq): NodeSeq = {         bind("entry", in,             "addNewKeyword" ­> SHtml.text("", newKeyword = _,  "maxlength" ­> "50"),             "submitNewKeyword" ­> SHtml.submit("Добавить",  addNewKeyword))    } private def addNewKeyword() { …         val kw =  <lift:clazz.keywordsForm form="POST"> KeywordsModel.create <entry:addNewKeyword />         kw.keyword(newKeyword) <entry:submitNewKeyword />         kw.save </lift:clazz.keywordsForm> } …
  • 31. ссылки • Обзор языка программирования Scala • Статьи на Habrahabr • Programming Scala • Scala Reference Manuals • Scala Style Guide • Exploring Lift • Lift Wiki