What can make scala more popular?

We do not have any problem to map case classes.
We usually do not use native sql at all for orm oriented task.
It is very inconvinient to work with query like:

     with userRole as (
        select u.id as idUser
              ,u.susername as sUser
              ,pg.idacrole
          from btk_user u
          join btk_acusergrant g on u.id = g.iduser
          join btk_acprofilegrant pg on g.idacprofile = pg.idacprofile
         where coalesce(u.bnotactive,0) = 0 and coalesce(u.bIsTemplate,0) = 0
              #$svFlt
      )
      select tt.idUser
            ,tt.sUser
            ,tt.sAcObj
            ,tt.idAcObj
            ,tt.sAcObjBundle
            ,tt.idAcObjBundle
            ,tt.sAcObjItem
            ,tt.idAcObjItem
            ,string_agg(tt.sPrivTypeCode||'.'||tt.sPrivName,chr(10)) as cPriv
        from (
            select ur.idUser
	              ,ur.sUser
	              ,o.scode as sAcObj
	              ,o.id as idAcObj
	              ,b.scaption as sAcObjBundle
	              ,b.id as idAcObjBundle
	              ,oi.scode as sAcObjItem
	              ,oi.id as idAcObjItem
	              ,pt.sCode as sPrivTypeCode
	              ,ip.ssystemname as sPrivName
	              ,max(r.bhasaccess) as bhasaccess
	              ,coalesce(max(r.bdenied), 0) as bdenied
	          from userRole ur
	          join btk_acrolegrantreg r
	            on r.idacrole = ur.idacrole
	          join btk_acroleobjectgranttype gt
	            on r.idacroleobjectgranttype = gt.id
	           and gt.scode = 'Element'
	          join BTK_ACItemPrivilege ip
	            on r.idacitemprivilege = ip.id
	           and coalesce(ip.bold,0) = 0
	          join btk_acprivilegetype pt
	            on ip.idacprivilegetype = pt.id
	          join btk_acitem i
	            on ip.idacitem = i.id
	           and coalesce(i.bold,0) = 0
	          join btk_acobjectitem oi
	            on i.id = oi.idacitem
	           and r.idacobjectitem = oi.id
	           and coalesce(oi.bold,0) = 0
	          join btk_acobjectbundle b
	            on oi.idacobjectbundle = b.id
	            and coalesce(b.bold,0) = 0
	          join btk_acobject o
	            on b.idacobject = o.id
	           and coalesce(o.bold,0) = 0
	         group by ur.idUser,
	                  ur.sUser,
	                  o.id,
	                  b.id,
	                  oi.scode,
	                  oi.id,
	                  pt.scode,
	                  ip.ssystemname
        ) tt
      where tt.bdenied = 0
        and tt.bhasaccess = 1
      group by tt.idUser
	            ,tt.sUser
	            ,tt.sAcObj
	            ,tt.idAcObj
	            ,tt.sAcObjBundle
	            ,tt.idAcObjBundle
	            ,tt.sAcObjItem
	            ,tt.idAcObjItem

It is just inconvenient to create a case class on each query.

Just for example of some table

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<class xmlns="http://www.global-system.ru/xsd/global3-class-1.0" name="Bs_Goods" caption="ТМЦ"
       cardEditor.representation="HeaderCard" listEditor.selection="List" viewOptions.openCardType="mdi"
       group.type="multi" group.root="Goods" objectAttrCardType="group">
    <mixins>
        <mixin name="Gds_GdsSrv" isDpiManaged="true"/>
        <mixin name="Gds_ControlObject" isDpiManaged="true"/>
    </mixins>
    <attributes>
        <attr name="id" attribute-type="Long" caption="Идентификатор" order="-1" isMnemoCode="true" type="basic"
              isVisible="false"/>
        <attr name="idClass" attribute-type="Long" caption="Класс" order="-10" type="basic" isVisible="false"/>
        <attr name="gidSrc" attribute-type="Varchar" caption="Объект-источник" order="0" type="refAnyObject"
              isVisible="false"/>
        <attr name="sArticle" attribute-type="Varchar" caption="Ном.№" order="10" isMnemoCode="true" type="basic"
              isVisible="true" isRequired="true">
            <mnemoCodeColumn/>
        </attr>
        <attr name="sDesignation" attribute-type="Varchar" caption="Обозначение" order="15" type="basic"
              isVisible="false">
        </attr>
        <attr name="sDesignationOld" attribute-type="Varchar" caption="Обозначение (старое)" order="16" type="basic"
              isVisible="false">
        </attr>
        <attr name="sShortName" attribute-type="Varchar" caption="Короткое наименование" order="15" type="basic"/>
        <attr name="sName" attribute-type="Varchar" caption="Наименование" order="20" isHeadLine="true" type="basic"
              isVisible="true" isRequired="true">
            <headLineColumn length="512"/>
        </attr>
        <attr name="sExternalName" attribute-type="Varchar" caption="Наименование внешней системы" order="21" type="basic"
              isVisible="false" isRequired="false">
            <headLineColumn length="512"/>
        </attr>
        <attr name="sPartNumber" attribute-type="Varchar" caption="Артикул" order="30" type="basic" isVisible="true"/>
        <attr name="sNomName" attribute-type="Varchar" caption="Условное наименование" order="35" type="basic"/>
        <attr name="idMeasureItem" attribute-type="Long" caption="ЕИ" order="40" type="refObject"
              isVisible="true" ref.class="Msr_MeasureItem" isRequired="true" isObjectAttr="true"/>
        <attr name="idMeasureItem2" attribute-type="Long" caption="БЕИ2" order="135" type="refObject" isVisible="true"
              ref.class="Msr_MeasureItem"/>
        <attr name="nRoundPlaces2" attribute-type="Number" caption="Точность округления БЕИ2" order="136" type="basic"
              isVisible="true"/>
        <attr name="nConvertBaseToBase2" attribute-type="Number" caption="Коэффициент пересчета БЕИ в БЕИ2" order="138"
              type="basic" isVisible="true"/>
        <attr name="nRoundPlaces" attribute-type="Number" caption="Точность округления БЕИ" order="50" type="basic"
              isVisible="true" isRequired="true"/>
        <attr name="idMsrNorm" attribute-type="Long" caption="ЕИ Нормирования" order="136" type="refObject" isVisible="false"
              ref.class="Msr_MeasureItem" genMnemoCodeColumn="true"/>
        <attr name="nRoundPlacesNorm" attribute-type="Number" caption="Точность округления ЕИ Нормирования" order="137" type="basic"
              isVisible="true"/>
        <attr name="nConvertBaseToBaseNorm" attribute-type="Number" caption="Коэффициент пересчета БЕИ в ЕИ Нормирования" order="138"
              type="basic" isVisible="true"/>
        <attr name="bNotActive" attribute-type="Number" caption="Не используется" order="60" type="basic"
              defaultValue="0" isVisible="true" editorType="check">
            <booleanColumn/>
        </attr>
        <attr name="dExpiryDate" attribute-type="Date" caption="Дата окончания использования" order="70" type="basic"
              isVisible="true" editorType="calendar"/>
        <attr name="idState" attribute-type="Long" caption="Состояние" order="80" type="refObject" isVisible="true"
              ref.class="Btk_ClassState" isCopyInCopyObject="false"/>
        <attr name="idStateMC" attribute-type="Number" caption="Состояние" order="85" type="basic" isVisible="false" isCopyInCopyObject="false"/>
        <attr name="sDescription" attribute-type="Varchar" caption="Описание" order="90" type="basic" isVisible="true">
            <descriptionColumn/>
        </attr>
        <attr name="idGoodsAndServiceType" attribute-type="Long" caption="Тип ТМЦ" order="100" type="refObject"
              isVisible="true" ref.class="Gds_GoodsAndServiceType"/>
        <attr name="idObjectType" attribute-type="Long" caption="Тип ТМЦ" order="100" type="refObject" isVisible="true" ref.class="Btk_ObjectType"/>
        <attr name="idObjectTypeCons" attribute-type="Long" caption="Тип партии прихода" order="100" type="refObject" isVisible="true" ref.class="Btk_ObjectType"/>
        <attr name="sIndexNumber" attribute-type="Varchar" caption="Каталожный номер" order="110" type="basic"
              isVisible="true"/>
        <attr name="sCodeOsk" attribute-type="Varchar" caption="Код ОСК" order="115" isVisible="true"/>
        <attr name="sNameMaker" attribute-type="Varchar" caption="Наименование производителя" order="120" type="basic"
              isVisible="true"/>
        <attr name="sInternationalCaption" attribute-type="Varchar" caption="Международное название" order="130"
              type="basic" isVisible="true"/>
        <attr name="bIsSet" attribute-type="Number" caption="Является комплектом" order="140" type="basic"
              defaultValue="0" isVisible="true" editorType="check">
            <booleanColumn/>
        </attr>
        <attr name="bRossip" attribute-type="Number" caption="Россыпь" order="145" type="basic"
              defaultValue="0" isVisible="true" editorType="check">
            <booleanColumn/>
        </attr>
        <attr name="sGost" attribute-type="Varchar" caption="ГОСТ" order="150" type="basic" isVisible="true"/>
        <attr name="idGost" attribute-type="Long" caption="ГОСТ" order="160" type="refObject" isVisible="true"
              ref.class="Bs_Gost"/>
        <attr name="idGrade" attribute-type="Long" caption="Марка ТМЦ" order="180" type="refObject" isVisible="true"
              ref.class="Gds_Grade"/>
        <attr name="idSortamentType" attribute-type="Long" caption="Тип сортамента" order="190" isObjectAttr="true"
              type="refObject" isVisible="true" ref.class="Gds_SortamentType"/>
        <attr name="idAccessMethod" attribute-type="Long" caption="Метод доступа для партий" order="195" type="refObject" isVisible="true" ref.class="Gds_AccessMethod"/>
        <attr name="gid" attribute-type="Varchar" type="basic"/>
        <attr name="gidSpecification" attribute-type="Varchar" type="refAnyObject" caption="Спецификация" order="200"
              isVisible="false"/>
        <attr name="gidDefSuite" attribute-type="Varchar" type="refAnyObject" caption="Набор по умолчанию" order="210"
              isVisible="false" ref.class="Gds_Suite"/>
        <attr name="idSupplyDepartment" attribute-type="Long" caption="Группа доступа к номенклатуре" order="210"
              type="refObject" ref.class="Gds_SupplyDepartment" isVisible="false" isObjectAttr="true"/>
        <attr name="idABCClassifier" attribute-type="Long" caption="Классификатор  А,В,С" order="220"
              type="refObject" ref.class="Gds_ABCClassifier" isVisible="false" editorType="combo"/>
        <attr name="idTypeSize" attribute-type="Long" caption="Типоразмер" order="230" type="refObject" isVisible="false" ref.class="Gds_TypeSize"/>
        <attr name="bPurchase" attribute-type="Number" caption="Закупка" order="240" editorType="check" defaultValue="0" isVisible="false">
            <booleanColumn/>
        </attr>
        <attr name="sCodeITSI" attribute-type="Varchar" caption="Код ИТСИ" order="250" isVisible="false" isObjectAttr="true"/>
        <attr name="nWeight" attribute-type="Number" caption="Масса" order="260" isVisible="false" isObjectAttr="true"/>
        <attr name="nUdelnVes" attribute-type="Number" caption="Удельный вес" order="270" isVisible="false" isObjectAttr="true"/>
        <attr name="nIntDiameter" attribute-type="Number" caption="Посадочный диаметр" order="280" isVisible="false" isObjectAttr="true"/>
        <attr name="nDiameterOftheWire" attribute-type="Number" caption="Диаметр проволоки, мм" order="290" isVisible="false" isObjectAttr="true"/>
        <attr name="nWidth" attribute-type="Number" caption="Ширина, м" order="300" isVisible="false" isObjectAttr="true"/>
        <attr name="nHeight" attribute-type="Number" caption="Высота, м" order="310" isVisible="false" isObjectAttr="true"/>
        <attr name="nVolume" attribute-type="Number" caption="Объём , м3" order="320" isVisible="false" isObjectAttr="true"/>
        <attr name="nAvutilizationrate" attribute-type="Number" caption="Коэффициент использования" order="330" isVisible="false" isObjectAttr="true"/>
        <attr name="sOkpo" attribute-type="Varchar" caption="Код ОКП" order="340" isVisible="false"/>
        <attr name="nDelDays" attribute-type="Number" caption="Длительность поставки, кален. дн." order="350" isVisible="false" isObjectAttr="true"/>
        <attr name="nPurchDays" attribute-type="Number" caption="Длительность зак. процедур, кален. дн." order="360" isVisible="false" isObjectAttr="true"/>
        <attr name="nManufDays" attribute-type="Number" caption="Длительности изготовления, кален. дн." order="370" isVisible="false" isObjectAttr="true"/>
        <attr name="nResDays" attribute-type="Number" caption="Страховой период, кален. дн." order="380" isVisible="false" isObjectAttr="true"/>
        <attr name="nLength" attribute-type="Number" caption="Длина" order="390" isVisible="false" isObjectAttr="true"/>
        <attr name="nThickness" attribute-type="Number" caption="Толщина" order="400" isVisible="false" isObjectAttr="true"/>
        <attr name="nDiameter" attribute-type="Number" caption="Диаметр" order="410" isVisible="false" isObjectAttr="true"/>
        <attr name="idPurchaseDirection" attribute-type="Long" caption="Направление закупок" order="420"
              type="refObject" isVisible="true" ref.class="Bs_PurchaseDirection" isObjectAttr="true"/>
        <attr name="idControlType" attribute-type="Long" caption="Тип входного контроля" order="430"
              type="refObject" isVisible="true" ref.class="Gds_ControlType" isObjectAttr="true"/>
        <attr name="bNeedCheckIn" attribute-type="Number" caption="Требуется входной контроль" order="440" editorType="check" defaultValue="0" isVisible="true" isObjectAttr="true">
            <booleanColumn/>
        </attr>
        <attr name="bDeliveredInKit" attribute-type="Number" caption="Является комплектующей" order="450" editorType="check" defaultValue="0" isVisible="true" isObjectAttr="true">
            <booleanColumn/>
        </attr>
        <attr name="idOKVED2" attribute-type="Long" caption="Оквэд" order="460" type="refObject" isVisible="true"
              ref.class="Bs_OKVED2" isObjectAttr="true"/>
        <attr name="idBudgetItem" attribute-type="Long" caption="Статья бюджета ОСК" order="470"
              type="refObject" isVisible="false" ref.class="Bs_BudgetItem" isObjectAttr="true"/>
        <attr name="idKind" attribute-type="Long" caption="Вид номенклатуры" order="480"
              type="refObject" isVisible="false" ref.class="Gds_Kind" isObjectAttr="true"/>
        <attr name="idResDimSetting" attribute-type="Long" caption="Настройка разреза резерва" order="490"
              type="refObject" isVisible="false" ref.class="Gds_ResDimSetting" isObjectAttr="true"/>
    </attributes>
    <collections>
        <collection cascadeOnDelete="true" name="Bs_GoodMsrItem" ref.attr="idGoods"/>
        <collection cascadeOnDelete="true" name="Gds_ArticleContras" ref.attr="idGds" сopyWithMaster="false"/>
        <collection cascadeOnDelete="true" name="Gds_Suite" ref.attr="idGds"/>
        <collection cascadeOnDelete="true" name="Gds_GoodsBarCode" ref.attr="idGds"/>
        <collection cascadeOnDelete="true" name="Bs_GoodsSrc" ref.attr="idGds"/>
        <collection cascadeOnDelete="true" name="Gds_Analogues" ref.attr="idGds"/>
        <collection cascadeOnDelete="true" name="Gds_ContrasCode" ref.attr="idGds" сopyWithMaster="false"/>
        <collection cascadeOnDelete="true" name="Gds_ContrasDesignation" ref.attr="idGds" сopyWithMaster="false"/>
        <collection cascadeOnDelete="true" name="Gds_ContrasCaption" ref.attr="idGds" сopyWithMaster="false"/>
        <var-collection name="Gds_GdsSrvTaxRate" ref.attr="gidGdsSrv"/>
        <var-collection name="Btk_ObjectGroup" ref.attr="gidSrcObject" сopyWithMaster="false"/>
    </collections>
    <dbSchema>
        <indexes>
            <index name="idx_bs_goods_sname" version="0">
                CREATE INDEX IF NOT EXISTS idx_bs_goods_sname ON public.bs_goods (sname)
            </index>
        </indexes>
    </dbSchema>
</class>

If you don’t want full static typing then you can use scala.Dynamic to save on number of classes.

I’ll base my example on H2 database. Add "com.h2database" % "h2" % "1.4.199" to your build definition. Then following example will work:

import java.sql.{ResultSet, Types}

import org.h2.tools.SimpleResultSet

import scala.language.dynamics
import scala.reflect.ClassTag

class DynamicResultSet(underlying: ResultSet) extends Dynamic {
  import underlying._

  def selectDynamic[ColumnType: ClassTag](columnLabel: String): ColumnType = {
    val erasedClass = implicitly[ClassTag[ColumnType]].runtimeClass
    getObject(columnLabel, erasedClass.asInstanceOf[Class[ColumnType]])
  }

  def updateDynamic(columnLabel: String)(cellValue: Any): Unit =
    updateObject(columnLabel, cellValue)
}

object DynamicResultSet {
  implicit class RichResultSet(val self: ResultSet) extends AnyVal {
    def dyn: DynamicResultSet = new DynamicResultSet(self)
  }

  def main(args: Array[String]): Unit = {
    // row set setup
    val rs = new SimpleResultSet()
    rs.addColumn("name", Types.VARCHAR, 10, 0)
    rs.addColumn("size", Types.SMALLINT, 10, 0)
    rs.addRow("a", 8: Number)
    rs.setAutoClose(false)
    rs.beforeFirst()
    rs.next()
    // using row set through scala.Dynamic
    val drs = rs.dyn
    println(drs.name[String]) // prints: a
    println(drs.size[Integer]) // prints: 8
    drs.name = "Johnny"
    drs.name = ("John": AnyRef) // still works, even with imprecise static type
    drs.size = 2
    println(drs.name[String]) // prints: John
    println(drs.size[Integer]) // prints: 2
  }
}

Unfortunately we use native sql exactly in cases where performance is important. We can use dynamics we can use java we can not use scala.

What kind of dynamism you want to avoid? scala.Dynamic trait works in a simple way:

    drs.name = "Johnny"
    println(drs.name[String]) // prints: Johnny
    // is translated during compile-time (not run-time) to
    drs.updateDynamic("name")("Johnny")
    println(drs.selectDynamic[String]("name")) // prints: Johnny

Is simple method call too pricey?

1 Like

When we need filtering or sorting for example, access by key will appear in a profile report. It is annoying.

Is there anything (in Scala, Kotlin, Java, whatever) that fullfills your very obscure requirements? I haven’t seen a single attempt at putting field indexes into a type system. The closest one is HLists but they don’t store field names (so that probably rules them out), just heterogenous types in order. Also emulating field access by traversing such HList would be expensive.

1 Like

Could you explain what is the motivation of the question. Is it necessary that a feature would exist in another language? I remember the time when scala was the first. White box macros can help.

No, it’s not necessary, but so far there isn’t even a clear direction. You haven’t even shown a full theoretical example with your desired syntax and how would it desugar to a working example in conventional Scala.

I have an impression that if you try too hard to make super-flexible mechanism then you’ll end up with something costly anyway. Records in Dotty https://github.com/lampepfl/dotty-feature-requests/issues/8 look like plenty of class casts and megamorphic calls in addition to a new HList instance created for every new row.

But again, it’s hard to optimize for use case that is not fully known. Show the actual working code and tell where is the redundancy that you would want to avoid.

2 Likes

OK, it is clear. I will try to create more detailed topic later. It is not easy task for me. I just do not know whether something is difficult or not. The main idea:

  • it should be array or product after compilation in bytecode
  • Scala should allow to use name instead index in code
  • The dinamics is allowed for whole dataset instead of each row.
  • it should be very usefull in such library like slick :slight_smile:

See: Discussion about structural types(Flyweight pattern)

Is there anything (in Scala, Kotlin, Java, whatever) that fullfills your very obscure requirements? I haven’t seen a single attempt at putting field indexes into a type system.

Yeah, there is at least Haskell superrecord library - SuperRecord: Anonymous Records for Haskell that morphs morphs labels to indices. SML#, according to stackoverflow, uses implicits to pass indexes for polymorphic records - Why doesn't OCaml support record subtyping? - Stack Overflow
Also, so far all discussed implementations of structural types for Haskell in https://github.com/ghc-proposals/ghc-proposals/pull/180 are index-based, not hashmap-based.

However, all of the above are for row types without subtyping, I’m not aware of any implementation of index-based access for subtyped structural types.

1 Like

Thank you. Before these links I felt very confused. Now, I know, There are people which solve such tasks. :slight_smile:

Since @AMatveev created topic Discussion about structural types(Flyweight pattern) we should use it for discussion about index-based record types. I have no clue why the topic name is so weird. What has “flyweight pattern” to do with index-based record types?

2 Likes

I really respect your stance.

Nevertheless it is too hard joke.
For example, sql is turing complete and it is functional. many people use other languages only because of mutability. :slight_smile:
And scala can not be better java if it fights against mutability :slight_smile:

Hmm. That’s an interesting assertion - it’s true that many languages are mutable, but I don’t know that there is much evidence that they are popular specifically because of mutability. I’d say that they are popular because they are easy. Which may be somewhat related (since most people learn mutable styles first, it’s easier for them to pick up), but isn’t the same thing …

2 Likes

Sorry, I have not said that popularity of any language depends on mutability, or simplicity. I think it is not the main point.

But I cannot imagine popular procedural language without mutability also :wink:

To say the truth I think the joke was around the words:

I sure that immutability of scala is butifull thing. But I think it will not good if it is the only killer feature. And if a procedural language does not have comfortable mutability it is not very good. I really like calling card like if you need big data processing the scala is for you. You will get mutability, immutability, object, fast record,macros. All what you need to quickly make fast reliable business app of any scale. I think it is more business oriented approach. :slight_smile:

1 Like

Making a language that is a kitchen sink of syntax features is not business friendly, I think. Look at C++ - it has everything and even more things are coming in next editions! You can write low-level code, high-level code, OOP code, functional code and even dysfunctional code. Only the last aspect was implemented properly :] How does C++ fare? Its significance diminishes. Less and less people want to deal with the absurdity of language complexity. Therefore we need to constraint the choices somewhat.

Scala community is already divided between two high-level programmers groups - pure FP ones and mixed OOP+FP ones. Adding low-level imperative coding lovers as a third group would mean even more division inside of Scala community. Do we want that? I don’t.

Big data, AI. machine learning and a lot of latest hot stuff (no matter how much sense it makes) is implemented in Python, which is a really slow language if you go through the route of writing pure Python code. If you want acceptable performance you need to find C libraries and write glue code in Python instead of writing real algorithms in Python. Scala is already much better than Python, performance wise.

Scala has mutability and will keep it. It’s just that mutability is second-class concern. Most of the time you should stick to functional programming.

Scala was never meant to be “better Java” (whatever that means). It’s not hard to find what Scala goals are. Look at Scala’s front page https://www.scala-lang.org/ :

There’s nothing about crazy mutations and low-level code. In fact it’s totally the opposite. Scroll down for “Online Courses” - you’ll see introduction to functional programming in Scala (totally non-imperative programming). Look at Scala conferences agendas - they are full of functional solutions to programming problems. It’s not surprising that when people hear “Scala” they think “functional programming on JVM” and not “extra sugar for Javaisms”.

In fact, if you look for “better Java” then two languages come to mind (three if you consider future Java to be another language than today’s Java):

  • C# which is touted as “Java done right” by C# programmers (that’s probably half-trolling, half-taking-pride) - C# wins the race of having the most keywords in a programming language
  • Kotlin which is designed to have a smooth learning curve for Java programmers and low friction integration with Java libraries and frameworks
  • Java itself is also developing, there are lambdas in Java 8, type inference (vars) in Java 10, future plans include pattern matching and data classes (counterpart of case classes)

So the competition is already tough. Scala is rather problematic if you compare it to the languages above. Scala breaks binary compatibility between versions (i.e. every two years or even more often), still has relatively slow compilation speed, has incompatible collections (so many frameworks and magical reflection-based libraries need special support for Scala). It would be hard to sell Scala as Java with extra syntactic sugar given these disadvantages.

Also, it seems to me it would be easier and more sensible to port the few Scala features you like to Kotlin than port the many Kotlin features you like to Scala. It’s really weird that you want to make Scala a Kotlin clone instead of just moving from Scala to Kotlin.

4 Likes

It is very doubtful analogy. It seems that its because of my words. But I can not see any connection. I like holy wars about c VS c++ but here is forum about scala… And I can repeat it for most other statement. I can make symmetric answer at least

Let me answer in same manner. I’ll be brief.

  • I feel tendency to isolation in last message.
    It seems there is nothing good in the sacrifice some language feature because of beautiful words.