ليست لغة برمجة أخرى. الجزء 1: منطق المجال



في الآونة الأخيرة ، ظهر عدد كبير من لغات البرمجة الجديدة في السوق: Go و Swift و Rust و Dart و Julia و Kotlin و Hack و Bosque - وهذه واحدة فقط من اللغات التي يتم الاستماع إليها.
من الصعب المبالغة في تقدير قيمة ما تجلبه هذه اللغات إلى عالم البرمجة ، ولكن كما لاحظ Y Combinator في العام الماضي عندما تحدثنا عن أدوات التطوير:
تتحسن الأطر ، واللغات أكثر ذكاء ، لكننا نفعل الشيء نفسه بشكل أساسي.
سوف تتحدث هذه المقالة عن لغة مبنية على نهج يختلف اختلافًا جوهريًا عن الأساليب المستخدمة في جميع اللغات الحالية ، بما في ذلك تلك المذكورة أعلاه. بشكل عام ، يمكن اعتبار هذه اللغة لغة متعددة الأغراض ، على الرغم من أن بعض قدراتها والتطبيق الحالي للمنصة المبنية عليها ، مع ذلك ، ربما يقصر تطبيقها على منطقة أضيق قليلاً - تطوير أنظمة المعلومات.

سأقوم بالحجز على الفور ، لا يتعلق بفكرة أو نموذج أولي أو حتى MVP ، ولكن عن لغة جاهزة للإنتاج كاملة بكل اللغات الأساسية للبنية التحتية - من بيئة التطوير (مع مصحح أخطاء) إلى الدعم التلقائي للعديد من إصدارات اللغة (مع دمج bugfixes تلقائي فيما بينها ، الإفراج عن مذكرة ، وما إلى ذلك). بالإضافة إلى ذلك ، باستخدام هذه اللغة ، تم بالفعل تنفيذ عدة عشرات من مشاريع تعقيد مستوى تخطيط موارد المؤسسات ، مع مئات المستخدمين المتزامنين ، وقواعد بيانات تيرابايت ، و "المواعيد النهائية للأمس" ، وميزانيات محدودة ومطورين دون خبرة في تكنولوجيا المعلومات. وكل هذا في نفس الوقت. حسنًا ، بالطبع ، تجدر الإشارة إلى أنه ليس عام 2000 ، وقد تم تنفيذ جميع هذه المشروعات على رأس الأنظمة الحالية (التي لم تكن موجودة) ، مما يعني أنه كان من الضروري في البداية القيام بـ "كما كان" تدريجياً ، دون إيقاف النشاط التجاري ، ثم ، أيضا تدريجيا ، تفعل ما ينبغي أن يكون. بشكل عام ، هذه هي الطريقة التي تبيع بها السيارات الكهربائية الأولى ليس لمحبى الأثرياء الأثرياء في كاليفورنيا ، ولكن إلى خدمات سيارات الأجرة منخفضة التكلفة في مكان ما في أومسك.

يتم إصدار منصة بنيت في هذه اللغة تحت رخصة LGPL v3. بصراحة ، لم أكن أرغب في كتابتها بشكل صحيح في المقدمة ، حيث أن هذا بعيد عن الميزة الأكثر أهمية لها ، ولكن ، مع التحدث إلى الأشخاص الذين يعملون في أحد أسواقها الرئيسية المحتملة - منصات ERP ، لاحظت ميزة واحدة: يقول كل هؤلاء الأشخاص دون استثناء أن حتى لو كنت تفعل الشيء نفسه الموجود في السوق بالفعل ، ولكن مجانًا ، سيكون رائعًا بالفعل. لذا اتركها هنا.

قليلا من الناحية النظرية


لنبدأ بالنظرية لتسليط الضوء على الاختلاف في النهج الأساسية المستخدمة في هذه اللغة وغيرها من اللغات الحديثة.

إن إخلاء المسئولية الصغيرة ، والأسباب الأخرى إلى حد ما هي محاولة لسحب البومة على الكرة الأرضية ، ولكن مع نظرية أساسية في البرمجة ، من حيث المبدأ ، دعنا نقول بصراحة ، ليس حقًا ، لذلك عليك استخدام ما لديك.

واحدة من المهام الأولى والرئيسية التي تحلها البرمجة هي مشكلة حساب قيم الوظائف. من وجهة نظر النظرية الحسابية ، هناك نهجين مختلفين بشكل أساسي لحل هذه المشكلة.

الطريقة الأولى هي الآلات المختلفة (أشهرها هي آلة تورينج) - نموذج يتكون من الحالة الحالية (الذاكرة) وآلة (المعالج) ، والتي في كل خطوة تغير هذه الحالة الحالية بطريقة أو بأخرى. ويسمى هذا النهج أيضًا بنية فون نيومان ، وهو الذي يقوم عليه جميع أجهزة الكمبيوتر الحديثة و 99 في المائة من اللغات الحالية.

يعتمد الأسلوب الثاني على استخدام العوامل ، حيث يتم استخدامه بواسطة ما يسمى الوظائف المتكررة بشكل جزئي (المشار إليها فيما يلي باسم ChRF). علاوة على ذلك ، فإن الفرق الأكثر أهمية بين هذا النهج ليس في استخدام العوامل على هذا النحو (العوامل ، على سبيل المثال ، هي أيضًا في البرمجة الهيكلية باستخدام النهج الأول) ، ولكن في إمكانية التكرار على جميع قيم الوظيفة (انظر عامل تقليل الحجة إلى أدنى حد) وفي غياب عملية الحساب.

مثل آلة تورينج ، وظائف تكرارية جزئية هي تورينج كاملة ، أي ، يمكن استخدامها لتحديد أي حساب ممكن. هنا ، نوضح على الفور أن كلاً من Turing machine و CRF هما فقط الحد الأدنى من القواعد ، ومن ثم سنركز عليها كنهج ، أي على طراز ذا ذاكرة المعالج وعلى نموذج مع المشغلين دون استخدام المتغيرات وإمكانية التكرار على جميع القيم يعمل على التوالي.

يحتوي نموذج الإبلاغ الموحد كنهج على ثلاث مزايا رئيسية:

  • هو أفضل بكثير الأمثل. وهذا ينطبق مباشرة على تحسين عملية حساب القيمة ، وإمكانية التوازي مع هذا الحساب. في النهج الأول ، يقدم التأثير اللاحق ، على العكس من ذلك ، تعقيدًا كبيرًا للغاية في هذه العمليات.
  • إنها أفضل بكثير ، أي بالنسبة للوظيفة المبنية ، يمكن أن تكون أكثر فعالية لتحديد كيفية تغيير قيمها عندما تتغير قيم الوظائف التي تستخدمها هذه الوظيفة المدمجة. بالمعنى الدقيق للكلمة ، هذه الميزة هي حالة خاصة من الأول ، ولكن هذه هي بالتحديد التي توفر عددًا كبيرًا من الاحتمالات ، والتي لا يمكن أن تكون أساسًا في النهج الأول ، وبالتالي يتم تمييزها كبند منفصل.
  • هو أسهل بكثير لفهم. بمعنى أن وصف وظيفة حساب مجموع مؤشر واحد في سياق مؤشرين آخرين أسهل بكثير في الفهم مما لو تم وصفه من حيث النهج الأول. ومع ذلك ، في المشاكل المعقدة حسابيًا ، يكون الموقف معاكسًا تمامًا ، لكن تجدر الإشارة إلى أن المشكلات المعقدة حسابيًا في الغالبية العظمى من المناطق جيدة إذا كانت 5٪. بشكل عام ، لتلخيص قليلاً ، فإن CRF هو الرياضيات ، وآلات تورينج هي علوم الكمبيوتر. تبعا لذلك ، تدرس الرياضيات تقريبا في رياض الأطفال ، وعلوم الكمبيوتر اختيارية ومن المدرسة الثانوية. بطبيعة الحال المقارنة ، بطبيعة الحال ، ولكن لا يزال يعطي نوعا من القياس في هذا الشأن.

آلات تورينج لها ميزتان على الأقل:

  • سبق ذكرها أفضل تطبيق في مشاكل معقدة حسابيًا
  • جميع أجهزة الكمبيوتر الحديثة مبنية على هذا النهج.

بالإضافة إلى ذلك ، في هذه المقارنة ، نتحدث فقط عن مهام حساب البيانات ؛ في مشاكل تغيير البيانات دون استخدام Turing machines ، لا يزال بإمكانك القيام به.

بعد قراءة هذا المكان ، سوف يسأل أي قارئ يقظ سؤالًا معقولًا: "إذا كان منهج CRF جيدًا ، فلماذا لا يستخدم بأي لغة حديثة مشتركة؟". لذلك ، في الواقع ، هذا ليس كذلك ، يتم استخدامه ، علاوة على ذلك ، في اللغة المستخدمة في الغالبية العظمى من أنظمة المعلومات الحالية. كما تعتقد ، هذه اللغة هي لغة SQL. هنا ، بالطبع ، سوف يعترض القارئ نفسه على أن SQL هي لغة الجبر العلائقي (أي ، العمل مع الجداول ، وليس الوظائف) ، وسيكون ذلك صحيحًا. رسميا. في الواقع ، يمكننا أن نتذكر أن الجداول الموجودة في قاعدة بيانات إدارة قواعد البيانات عادةً ما تكون في الشكل العادي الثالث ، أي أنها تحتوي على أعمدة مفاتيح ، مما يعني أنه يمكن اعتبار أي عمود متبق من هذا الجدول بمثابة وظيفة لأعمدة المفاتيح الخاصة به. ليس واضحا ، بصراحة. ولماذا لم ينمو SQL من لغة الجبر العلائقية إلى لغة برمجة كاملة (أي ، العمل مع الدوال) هو سؤال كبير. في رأيي ، هناك العديد من الأسباب لذلك ، وأهمها "لا يمكن لأي شخص روسي (في الواقع أي شخص) العمل على معدة فارغة ، لكنه لا يريد العمل على تغذية جيدة" ، بمعنى أنه ، كما تبين الممارسة ، العمل اللازم لهذا إنه عملاق حقًا ويتحمل الكثير من المخاطر بالنسبة للشركات الصغيرة ، وبالنسبة للشركات الكبيرة ، أولاً ، كل شيء على ما يرام ، وثانيًا ، من المستحيل فرض هذا العمل بالمال - الجودة مهمة هنا ، وليس الكمية. في الواقع ، فإن التوضيح الأكثر وضوحًا لما يحدث عندما يحاول الأشخاص حل مشكلة من حيث الكمية بدلاً من الجودة هو Oracle ، الذي تمكن حتى من تطبيق أبسط تطبيقات التزايدية - تم تحديث العروض الملموسة بحيث تحتوي هذه الآلية على عدد من القيود من عدة صفحات (العدالة) من أجل ذلك ، مايكروسوفت لا تزال أسوأ ). ومع ذلك ، هذه قصة منفصلة ، وربما سيكون هناك مقال منفصل حول هذا الموضوع.

في الوقت نفسه ، ليس الأمر أن SQL سيئة. لا. على مستوى التجريد ، فإنه يؤدي وظائفه بشكل مثالي ، والتطبيق الحالي للنظام الأساسي يستخدمه أقل قليلاً من بالكامل (في أي حال ، أكثر بكثير من جميع المنصات الأخرى). شيء آخر هو أنه بعد ولادتها مباشرة ، توقفت SQL بالفعل عن التطور ولم تصبح ما يمكن أن تصبح ، أي اللغة التي سيتم مناقشتها الآن.

ولكن نظرية كافية ، فقد حان الوقت للذهاب مباشرة إلى اللغة.

لذلك ، نلتقي :


على وجه التحديد ، ستكون هذه المقالة الجزء الأول من ثلاثة (حيث لا يزال هناك الكثير من المواد حتى لمقالين) ، وسوف نتحدث فقط عن النموذج المنطقي - أي فقط حول ما يرتبط مباشرة بوظيفة النظام ولا يرتبط بالعمليات التطوير والتنفيذ (تحسين الأداء). علاوة على ذلك ، سنتحدث فقط عن أحد جزأين من النموذج المنطقي - منطق منطقة الموضوع. يحدد هذا المنطق المعلومات التي يخزنها النظام وما يمكنك القيام به بهذه المعلومات (عند تطوير تطبيقات الأعمال ، غالباً ما يطلق عليه منطق الأعمال).

بيانياً ، يمكن تمثيل جميع مفاهيم منطق المجال في lsFusion بالصورة التالية:


تشير الأسهم في هذه الصورة إلى اتجاهات استخدام مفاهيم بعضها البعض ، وبالتالي ، فإن المفاهيم تشكل نوعًا من المكدس ، وبالتالي ، في ترتيب هذه المجموعة ، سأتحدث عنها.


الخصائص


الخاصية عبارة عن تجريد يأخذ كائنًا واحدًا أو أكثر كمعلمات ويعيد بعض الكائنات كنتيجة لذلك. الخاصية ليس لها تأثير لاحق ، وفي الواقع ، هي وظيفة محض ، ومع ذلك ، على عكس الأخير ، لا يمكن حساب القيم فقط ، ولكن أيضًا تخزينها. في الواقع ، يتم استعارة اسم "الملكية" نفسه من لغات البرمجة الحديثة الأخرى ، حيث يتم استخدامه لنفس الأغراض تقريبًا ، ولكن يتم تسميته للتغليف ، وبالتالي ، يتم دعمه فقط للوظائف ذات المعلمة الواحدة. حسنًا ، حقيقة أن كلمة "الملكية" ذاتها أقصر من "الوظيفة النقية" ، بالإضافة إلى عدم وجود رابطات غير ضرورية ، لعبت لصالح استخدام هذا المصطلح بعينه.

يتم تعيين الخصائص بشكل متكرر باستخدام مجموعة محددة مسبقًا من العوامل. هناك الكثير من هؤلاء المشغلين ، وبالتالي ، فإننا نعتبر فقط المشغلين الرئيسيين (هؤلاء المشغلون يغطون 95 ٪ من أي مشروع ثابت في المتوسط).

الملكية الرئيسية (البيانات)


الخاصية الأساسية هي خاصية يتم تخزين قيمتها في قاعدة البيانات ويمكن تغييرها كنتيجة للإجراء المقابل (عنها بعد ذلك بقليل). بشكل افتراضي ، تكون قيمة كل خاصية من هذه الخصائص لأي مجموعة من المعلمات مساوية لقيمة NULL خاصة.
quantity = DATA INTEGER (Item);
isDayOff = DATA BOOLEAN (Country, DATE);
, ( ), .

. :

class X { 	
    Y y; 	
    Map<Y, Z> f; 	
    Map<Y, Map<M, Z>> m; 	
    List<Y> n;
    LinkedHashSet<Y> l; //   
    static Set<Y> s;
}

:
y = DATA Y (X);
f = DATA Z (X, Y);
m = DATA Z (X, Y, M);
n = DATA Y (X,INTEGER);
l = DATA INTEGER (X,Y);
s = DATA BOOLEAN (Y);

(JOIN), , (+,-,/,*), (AND, OR), (+, CONCAT), (>,<,=), (CASE, IF), (IS)

f(a) = IF g(h(a)) > 5 AND a IS X THEN ‘AB’ + ‘CD’ ELSE x(5);
- , . , , , :

  • , . , ( NULL). , lsFusion – , , , – TRUE ( FALSE NULL), 3-state’.
  • NULL: (+), (-), CONCAT . :
    • : NULL 0, – , 0 NULL ( 5 (+) NULL = 5, 5 (-) 5 = NULL, 5 + NULL = NULL 5 — 5 = 0).
    • : NULL ( CONCAT ‘ ‘, ‘John’,’Smith’ = ‘John Smith’, CONCAT ‘ ‘, ‘John’, NULL = ‘John’, ‘John’ + ‘ ‘ + NULL = NULL).
  • (IF) ( ) : f(a) IF g(a), f(a) g(a) NULL, NULL – .

(GROUP)


– . (, ) .

:

  • :
    sum(Invoice i) = GROUP SUM sum(InvoiceDetail id) IF invoice(id) = i;
    currentBalance(Sku sk) = GROUP SUM currentBalance(sk, Stock st);
    , ( i sk). , , - :
    x() = (GROUP SUM f(a)) + 5;
  • SQL-:
    sum = GROUP SUM sum(InvoiceDetail id) BY invoice(id);
    currentBalance = GROUP SUM currentBalance(Sku sk, Stock st) BY sk;
    ( , , )

, ( ), – ( ). , , , ( , , SQL – ). , ( BY), - :
// BY     ,   s
sum(DATE from, Stock s, DATE to) = GROUP sum(Invoice i) IF date(i) >= from AND date(i) <=to BY stock(i); 
, , , , , .

:

  • /,

  • .

/ (PARTITION … ORDER)


( , ) , . , ( , ). / .
place(Team t) = PARTITION SUM 1 ORDER DESC points(t) BY conference(t);
, , , , , , .

SQL ( , ) (OVER PARTITION BY… ORDER BY).

(RECURSION)


– , . , , .

. , ( ):

  • (result) ( ) :
    • result(0, o1, o2, ..., oN) = initial(o1, ..., oN), initial –
    • result(i+1, o1, o2, ..., oN) = step(o1, ..., oN, $o1, $o2, ..., $oN) IF result(i, $o1, $o2, ..., $oN), step – .
  • , ( o1, o2, …, oN). , .

, , , , :
//   integer  from  to (       System)
iterate(i, from, to) = RECURSION i=from STEP i=$i+1 AND i<=to CYCLES IMPOSSIBLE;
 
//      a  b   ( ,  ,  )
edge = DATA BOOLEAN (Node, Node);
pathes '- ' (a, b) = RECURSION 1 IF b=a STEP 1 IF edge(b, $b);
 
// ,     child  parent,  null,     (         child')
parent  = DATA Group (Group);
level '' (Group child, Group parent) = RECURSION 1 AND child IS Group AND parent = child STEP 1 IF parent = parent($parent);
 
//  ,        to, (   NULL)
fib(i, to) = RECURSION 1 IF (i=0 OR i=1STEP 1 IF (i=$i+1 OR i=$i+2AND i<to CYCLES IMPOSSIBLE;
, / , , , .

, , , , , lsFusion – .

SQL CTE, , , . , Postgres GROUP BY , , , , , , . , , WHILE’ .

. , , .


– , , , , ( , , ). , , “”, , -, , , -, , “”.

, – lsFusion. , – . , – ( , , , ). , – . .

, . / , , , , , . 3 97, lsFusion – 60 40.

, , . , -, ( , ), .

, :

(FOR), (WHILE)


, lsFusion , , NULL ( ).
FOR selected(Team team) DO
    MESSAGE 'Team ' + name(team) + ' was selected';
, :
showAllDetails(Invoice i) {
    FOR invoice(InvoiceDetail id) = i ORDER index(id) DO
        MESSAGE 'Sku : ' + nameSku(id) + ', ' + quantity(id);
}
, , (IF).

(WHILE) , :

  • , NULL ( )


(EXEC), ({…}), (CASE, IF), (BREAK), (RETURN)

f(a) {
    FOR t=x(b,a) DO {
        do(b);
        IF t>5 THEN
            BREAK;
    }
    MESSAGE 'Succeeded';
}
- . , , .

(CHANGE)


. , , , , NULL. :
//       
setDiscount(Customer c)  {
    discount(c, Item i) <- 15 WHERE selected(i);
}
, :
setDiscount(Customer c)  {
    FOR selected(Item i) DO
        discount(c, i) <- 15;
}
, , , ( , , , , selected discount – ), . , , .

(NEW)


( , , , , ). , , .

:
newSku ()  {
    LOCAL addedSkus = Sku (INTEGER);
    NEW Sku WHERE iterate(i, 13TO addedSkus(i);
    FOR Sku s = addedSkus(i) DO {
        id(s) <- 425;
        name(s) <- 'New Sku : ' + i;
    }
}
, , — NEW (FOR), ( ):
FOR iterate(i, 13NEW s=Sku DO  {
    id(s) <- i;
    name(s) <- 'New Sku : ' + i;
}
, FOR :
NEW s=Sku DO {
    id(s) <- 425;
    name(s) <- 'New Sku';
}
– , , , .

(DELETE)


– :
DELETE Sku s WHERE name(s) = 'MySku';
, «» .

, , .


, , . , , . .

, . , — / .

, , . , ( ), .

, , . , :
LOCAL f = INTEGER (INTEGERINTEGER);

f(1,3) <- 6;
f(2,2) <- 4;
f(f(1,3),4) <- 5;
f(a,a) <- NULL//      1-  2-  (  2,2)

MESSAGE GROUP CONCAT a + ',' + b + '->' + f(a, b),' ; '//  1,3->6 ; 6,4->5
: (APPLY) (CANCEL). , , , . , , , . – , , , , . — .

(NEWSESSION, NESTEDSESSION)


(, , http- ..). , , . , , , «», «» ( , ). NEWSESSION, ( ). :
run() {
    f(1) <- 2;
    APPLY;
    f(1) <- 1;
    NEWSESSION {
        MESSAGE f(1); //  2,       
        f(2) <- 5;
        APPLY;          
    }
    MESSAGE f(1); //  1,     1  ,   
}
, , , . , :
run(Store s) {
    NEWSESSION
        MESSAGE 'I see that param, its name is: ' + name(s);
}
, , ( ). NESTED, , , , . , ( , NESTED). :
g = DATA LOCAL NESTED INTEGER ();
run() {
    f(1) <- 1; g() <- 5;
    NEWSESSION NESTED (f) {
        MESSAGE f(1) + ' ' + g(); //  1 5
        f(1) <- 5; g() <- 7;
    }
    MESSAGE f(1) + ' ' + g(); //  5 7
}
. :

  • , , , < —
  • , , : < —
  • , : < — .

, (, ), , . , , - , , , , , :


  • ,

(APPLY), (CANCEL)


– , . , . , :

  • . , , , NESTED ( ).
  • , . , - , , , . , (update conflict), , , . , :

// -------------------------- Object locks ---------------------------- //
 
locked = DATA User (Object);
lockResult = DATA LOCAL NESTED BOOLEAN ();
 
lock(Object object)  {
    NEWSESSION { 
        lockResult() < - NULL;
        APPLY SERIALIZABLE {
            IF locked(object) THEN {
                CANCEL;
            } ELSE {
                locked(object) <- currentUser();
                lockResult() <- TRUE;
            }
        }
    }
}
 
unlock(Object object)  {
    NEWSESSION
        APPLY locked(object) <- NULL;
}
PS: Authentication, , , ( ) ( ). , , lsFusion , (, ).

– , , , , ( ).

(PREV, CHANGED, SET, DROPPED)


: (PREV), (CHANGED), NULL NULL (SET) .. ( ), , , :
f = DATA INTEGER (INTEGER);
run() {
    f(1) <- 2;
    APPLY;
 
    f(1) <- 5;
    f(2) <- 3;
    MESSAGE GROUP SUM 1 IF CHANGED(f(a)); // ,    f     ,  2
    MESSAGE '. : ' + f(1) + ', . : ' + PREV(f(1)); //  . : 5, . : 2
}
. , , , , .


“ ?”, “ ?”. , , .

, , . , . .

:

  • – .
  • – , / .

, , :

  • – .
  • – .

, , , .

:

  • , , , .
  • , .

:

  • , « ». , , , ( , , 5-10 , ).
  • , ( ), , , , .

:

  • , , .

:

  • , , ( ), , .

( , ), .
ON { //   ,       APPLY
    MESSAGE 'Something changed';
}
, , , , ‘Something changed’ (!) ( , ). , , - , (CHANGED, SET, DROPPED ..). , - , -, -. – :
//  email,          
WHEN SET(balance(Sku s, Stock st) < 0DO
      EMAIL SUBJECT '     ' + name(s) + '   ' + name(st);

WHEN LOCAL CHANGED(customer(Order o)) AND name(customer(o)) == 'Best customer' DO
    discount(OrderDetail d) <- 50 WHERE order(d) = o;

, – , . , :
ON {
    FOR SET(balance(Sku s, Stock st) < 0DO
        EMAIL SUBJECT '     ' + name(s) + '   ' + name(st);
}
, , / , , .

SQL ( ) . , , , ( ) , .

, :

  • – , ( )
  • – , . , , «» .


, , . , , NULL:
//    0
CONSTRAINT balance(Sku s, Stock st) < 0 
    MESSAGE '    ';

// ""  
CONSTRAINT DROPCHANGED(barcode(Sku s)) AND name(currentUser()) != 'admin' 
    MESSAGE ' -       ';

//      ,   
CONSTRAINT sku(OrderDetail d) AND NOT in(sku(d), customer(order(d)))
    MESSAGE '        ';
, – , NULL (SET) , – NULL . – , , , / , .

, – ( ), , , ( ), , .


. , , , – . , :
f = DATA A (INTEGER);
, f NULL , A. :
f = Object (INTEGER);
CONSTRAINT f(i) AND NOT f(i) IS A MESSAGE ' '// f(i) => f(i) IS A
, , – . ( , , «»), , , , : - , .

, lsFusion . , lsFusion . , . lsFusion , , - :
CLASS A {
    f = DATA LONG (INTEGER); //  f = DATA LONG (A, INTEGER)
}
lsFusion , :
CLASS Animal;
CLASS Transport;
CLASS Car : Transport;
CLASS Horse : Transport, Animal;
, – .


lsFusion – . , , :
speed = ABSTRACT LONG (Transport);
/ , :
CLASS Breed;
speed = DATA LONG (Breed)
breed = DATA Breed (Animal);

speed(Horse h) += speed(breed(h)); //       
( ):
CLASS Thing;
CLASS Ship : Thing;
CLASS Asteroid : Thing;

collide ABSTRACT (Thing, Thing);
collide(Ship s1, Ship s2) +{
    MESSAGE 'Ship : ' + name(s1) + ', Ship : ' + name(s2);
}
collide(Ship s1, Asteroid a2) +{
    MESSAGE 'Ship : ' + name(s1) + ', Asteroid : ' + name(a2);
}
collide(Asteroid a1, Ship s2) +{
    MESSAGE 'Asteroid : ' + name(a1) + ', Ship : ' + name(s2);
}
collide(Asteroid a1, Asteroid a2) +{
    MESSAGE 'Asteroid : ' + name(a1) + ', Asteroid : ' + name(a2);
}
, , ( ), . ABSTRACT :
speed(Transport t) = CASE 
    WHEN t IS Horse THEN speed(breed(t))
    //  
END
, .

, , :
speed(Horse h) = speed(breed(h));
, , ( ). , , .


, , . () : , , . , , , , , . NULL , , :
f = DATA LONG (LONG);
g = DATA LONG (A);
h(a) = OVERRIDE f(a), g(a); //   


( ) – , . , , , :
CLASS Direction '' {
    left '',
    right '',
    forward ''
}

result(dir) = CASE
    WHEN dir = Direction.left THEN ' '
    WHEN dir = Direction.right THEN ' '
    WHEN dir = Direction.forward THEN ' '
END
, .

enum’, , .


( lsFusion, ) :

  • ( ).
  • ( ).
  • .

.

() , NULL . , , , , , .

:
//   A    B
b(A a) = AGGR B WHERE a IS A; 
//     a     B    A,   b(a(b)) = b

createC = DATA BOOLEAN (A, B)
//    A  B    createC    C
//     ,       ,      
c = AGGR C WHERE createC(A a, B b); 
//     a  b     C      B 
, , ( ):
CLASS Shipment '';
date = ABSTRACT DATE (Shipment);
CLASS Invoice '';
createShipment ' ' = DATA BOOLEAN (Invoice);
date ' ' = DATA DATE (Invoice);
CLASS ShipmentInvoice '  ' : Shipment;
//    ,       
shipment(Invoice invoice) = AGGR ShipmentInvoce WHERE createShipment(invoice);
date(ShipmentInvoice si) += sum(date(invoice(si)),1); //   =   + 1
, (, ), ( ) , . , ERP 1100 . , , , . , ( 50 ), , 1100 300 .

, , , , . , , – , – , , , « - », , , .


, lsFusion . , , , , , , , , , ( , , ). , lsFusion ( ACID), , SQL-, . , DSL lsFusion , , – – . , SQL , , lsFusion . , , – , github ( , ), (IDE, , VCS, ), slack telegram- , (linux maven, - ), , , , , lsFusion , SQL, ABAP 1 – .

, , lsFusion, , ( ), : ERP-, SQL- , ORM-, RAD-, . , , .

, :

  • SQL- – - – , , .
  • ERP- – - – , , ..
  • ORM- – - (, ), .
  • RAD – - , , , IT-.
  • – , RAD, , - , , Excel (, , , – ).

, lsFusion ERP, RAD SQL , lsFusion ( ). , SQL, , , , , , Fortran C ( , ). ORM- , – . , , - .

SME ( , ), ( ). , 1 , .

, , , , , ( 12 ), .

UPD: .

Source: https://habr.com/ru/post/ar458376/


All Articles