SlideShare a Scribd company logo
+

Дмитрий Стропалов, Александр Михальчук
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

More Related Content

What's hot (14)

PDF
Лекция 1. Начало.
Roman Brovko
 
PPT
Производительность в Django
MoscowDjango
 
PDF
Метапрограммирование за гранью приличия
Alexander Schepanovski
 
PDF
Лекция 5. Встроенные коллекции и модуль collections.
Roman Brovko
 
ODP
Scala - my path
Анатолий Ботов
 
PPT
9. java lecture library
MERA_school
 
PDF
Лекция 12. Быстрее, Python, ещё быстрее.
Roman Brovko
 
PPT
8. java lecture threads
MERA_school
 
PPTX
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Fedor Lavrentyev
 
PPT
Декораторы в Python и их практическое использование
Sergey Schetinin
 
PDF
Лекция 8. Итераторы, генераторы и модуль itertools.
Roman Brovko
 
PDF
Профилирование и отладка Django
Vladimir Rudnyh
 
PDF
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Roman Brovko
 
PDF
Лекция 3. Декораторы и модуль functools.
Roman Brovko
 
Лекция 1. Начало.
Roman Brovko
 
Производительность в Django
MoscowDjango
 
Метапрограммирование за гранью приличия
Alexander Schepanovski
 
Лекция 5. Встроенные коллекции и модуль collections.
Roman Brovko
 
9. java lecture library
MERA_school
 
Лекция 12. Быстрее, Python, ещё быстрее.
Roman Brovko
 
8. java lecture threads
MERA_school
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Fedor Lavrentyev
 
Декораторы в Python и их практическое использование
Sergey Schetinin
 
Лекция 8. Итераторы, генераторы и модуль itertools.
Roman Brovko
 
Профилирование и отладка Django
Vladimir Rudnyh
 
Лекция 2. Всё, что вы хотели знать о функциях в Python.
Roman Brovko
 
Лекция 3. Декораторы и модуль functools.
Roman Brovko
 

Viewers also liked (8)

PPT
презентация12
MartiniAnn
 
PDF
The Darwish Resistance: The Clash Between Somali Clanship And State System
Taibah University, College of Computer Science & Engineering
 
PDF
Drd700
ciperi
 
DOC
11e2d ass1
Mukund Trivedi
 
PPT
F acebook:twitter
Gray122
 
PDF
Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...
encartaciones
 
PPT
Solution to assignment 1
Liu Liu
 
PDF
Devoxx 2010 | LAB : ReST in Java
NGDATA
 
презентация12
MartiniAnn
 
The Darwish Resistance: The Clash Between Somali Clanship And State System
Taibah University, College of Computer Science & Engineering
 
Drd700
ciperi
 
11e2d ass1
Mukund Trivedi
 
F acebook:twitter
Gray122
 
Udalberriak 156 - Noviembre 2012 - Día Internacional contra la violencia haci...
encartaciones
 
Solution to assignment 1
Liu Liu
 
Devoxx 2010 | LAB : ReST in Java
NGDATA
 
Ad

Similar to Scala and LiftWeb presentation (Russian) (20)

PDF
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
ScalaNsk
 
PPTX
Зачем нужна Scala?
Vasil Remeniuk
 
PDF
Groovy presentation.
Infinity
 
PDF
Scala, Play Framework и SBT для быстрого прототипирования и разработки веб-пр...
Magneta AI
 
PDF
Язык программирования Scala / Владимир Успенский (TCS Bank)
Ontico
 
PDF
Scala, SBT & Play! for Rapid Application Development
Anton Kirillov
 
PDF
Scala for Android Explained
Matvey Malkov
 
PPT
Groovy On Grails
guest32215a
 
PDF
Scala lecture #4
Alexander Podkhalyuzin
 
PDF
Павел Павлов - Scala для профессионалов - Joker 2013
ScalaNsk
 
PDF
Scala: что, как и зачем?
Roman Timushev
 
PPTX
Kotlin
GDG Odessa
 
PPTX
Scala для всех (РИФ 2015)
Арсений Жижелев
 
PPTX
Xtend
Zheka Kozlov
 
PDF
Scala Rock-Painting
GlobalLogic Ukraine
 
PPTX
[Expert Fridays] Java MeetUp - Борис Ташкулов (Teamlead Enterprise): "Почему ...
Provectus
 
PPT
Характерные черты функциональных языков программирования
Alex.Kolonitsky
 
PDF
Lift, play, akka, rails part1
Eduard Antsupov
 
Павел Павлов - Scala для Java программистов (JavaDay Nsk 28.11.2013)
ScalaNsk
 
Зачем нужна Scala?
Vasil Remeniuk
 
Groovy presentation.
Infinity
 
Scala, Play Framework и SBT для быстрого прототипирования и разработки веб-пр...
Magneta AI
 
Язык программирования Scala / Владимир Успенский (TCS Bank)
Ontico
 
Scala, SBT & Play! for Rapid Application Development
Anton Kirillov
 
Scala for Android Explained
Matvey Malkov
 
Groovy On Grails
guest32215a
 
Scala lecture #4
Alexander Podkhalyuzin
 
Павел Павлов - Scala для профессионалов - Joker 2013
ScalaNsk
 
Scala: что, как и зачем?
Roman Timushev
 
Kotlin
GDG Odessa
 
Scala для всех (РИФ 2015)
Арсений Жижелев
 
Scala Rock-Painting
GlobalLogic Ukraine
 
[Expert Fridays] Java MeetUp - Борис Ташкулов (Teamlead Enterprise): "Почему ...
Provectus
 
Характерные черты функциональных языков программирования
Alex.Kolonitsky
 
Lift, play, akka, rails part1
Eduard Antsupov
 
Ad

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