Действительно декларативный язык?

Кто-либо знает о действительно декларативном языке? Поведение, которое я ищу, отчасти, что делает Excel, где я могу определить переменные и формулы, и иметь изменение результата формулы, когда вход изменяется (не установив ответ снова сам)

Поведение, которое я ищу, лучше всего показывают с этим псевдо кодом:

X = 10     // define and assign two variables
Y = 20;

Z = X + Y  // declare a formula that uses these two variables

X = 50     // change one of the input variables

?Z         // asking for Z should now give 70 (50 + 20)

Я попробовал это на большом количестве языков как F#, Python, matlab и т.д., но каждый раз я пробую это, они придумывают 30 вместо 70. Который корректен с обязательной точки зрения, но я ищу более декларативное поведение, если Вы понимаете, о чем я.

И это - просто очень простое вычисление. Когда вещи становятся более трудными, это должно обработать материал как рекурсия и memoization автоволшебно.

Код ниже, очевидно, работал бы в C#, но это - именно так много кода для задания, я ищу что-то немного больше к точке без всего этого 'технического шума'

class BlaBla{
    public int X {get;set;}  // this used to be even worse before 3.0
    public int Y {get;set;}
    public int Z {get{return X + Y;}}
}

static void main(){
   BlaBla bla = new BlaBla();
   bla.X = 10;
   bla.Y = 20;
   // can't define anything here
   bla.X = 50; // bit pointless here but I'll do it anyway. 
   Console.Writeline(bla.Z);// 70, hurray!
}

Это просто походит на такое большое количество кода, фигурных скобок и точек с запятой, которые ничего не добавляют.

Существует ли язык / приложение (кроме Exel), который делает это? Возможно, я - не делать правильно его на упомянутых языках, или я полностью пропустил приложение, которое делает просто это.

Я моделировал язык / приложение, которое делает это (наряду с некоторым другим материалом) и думает о productizing он. Я просто не могу полагать, что это еще не там. Не хочу тратить впустую свое время.

21
задан darthbith 21 August 2017 в 09:02
поделиться

19 ответов

Любая система программирования с ограничениями сделает это за вас. Примерами систем CP, имеющих связанный язык, являются ECLiPSe, SICSTUS Prolog / CP пакет, Comet, MiniZinc, ....

17
ответ дан 16 October 2019 в 23:39
поделиться

Это не то, что вы ищете, но языки описания оборудования по определению являются «декларативными».

-1
ответ дан 16 October 2019 в 23:39
поделиться

Вот пример Дэниела на Python, поскольку я заметил, что вы сказали, что пробовали его на Python.

x = 10
y = 10

z = lambda: x + y

# Output: 20
print z()

x = 20

# Output: 30
print z()
3
ответ дан 16 October 2019 в 23:39
поделиться

В системе Mathematica вы можете сделать следующее:

x = 10;     (* # assign 30 to the variable x *)
y = 20;     (* # assign 20 to the variable y *)
z := x + y; (* # assign the expression x+y to the variable z *)
Print[z];
(* # prints 30 *)
x = 50;
Print[z];
(* # prints 70 *)

Оператор : = (SetDelayed) отличается от = (Set). Первый связывает неоцененное выражение с переменной, последний связывает оцененное выражение .

9
ответ дан 16 October 2019 в 23:39
поделиться

Groovy и магия замыканий.

def (x, y) = [ 10, 20 ]

def z = { x + y }

assert 30 == z()

x = 50

assert 70 == z()

def f = { n -> n + 1 }  // define another closure

def g = { x + f(x) }    // ref that closure in another

assert 101 == g()       // x=50, x + (x + 1)

f = { n -> n + 5 }     // redefine f()

assert 105 == g()      // x=50, x + (x + 5)

Можно добавить автоматическую мемоизацию и в функции, но это намного сложнее, чем просто одна или две строки. http://blog.dinkla.net/?p=10

0
ответ дан 16 October 2019 в 23:39
поделиться

Есть библиотека Lisp с подобным поведением:

http://common-lisp.net/project/cells/

2
ответ дан 16 October 2019 в 23:39
поделиться

Две вещи, на которые вы можете обратить внимание, - это библиотека cells lisp и язык динамического моделирования Modelica , оба из которых имеют возможности отношений / уравнений.

2
ответ дан 16 October 2019 в 23:39
поделиться

Вы видели Resolver One? Это как Excel с настоящим языком программирования за спиной.

3
ответ дан 16 October 2019 в 23:39
поделиться

Похоже, вы просто хотите, чтобы Z сохраняла функцию вместо значения. В C #:

var X = 10;    // define and assign two variables
var Y = 20;

Func<int> Z = () => X + Y;  // declare a formula that uses these two variables

Console.WriteLine(Z());

X = 50;     // change one of the input variables

Console.WriteLine(Z());

Таким образом, эквивалентом синтаксиса префикса ? является суффикс () , но в остальном он идентичен. Лямбда - это «формула» в вашей терминологии.

За кулисами компилятор C # строит почти в точности то, что вы представили в концептуальном примере C #: он превращает X в поле в классе, созданном компилятором, и выделяет экземпляр этого класса, когда кодовый блок введен. Поздравляем, вы заново открыли лямбды! :)

15
ответ дан 16 October 2019 в 23:39
поделиться

В F #, немного многословно:

let x = ref 10
let y = ref 20

let z () = !x + !y

z();;
y <- 40
z();;
0
ответ дан 16 October 2019 в 23:39
поделиться

react - это библиотека OCaml frp. В отличие от наивных эмуляций с замыканиями, он будет пересчитывать значения только при необходимости

        Objective Caml version 3.11.2

# #use "topfind";;
# #require "react";;
# open React;;
# let (x,setx) = S.create 10;;
val x : int React.signal = <abstr>
val setx : int -> unit = <fun>
# let (y,sety) = S.create 20;;
val y : int React.signal = <abstr>
val sety : int -> unit = <fun>
# let z = S.Int.(+) x y;;
val z : int React.signal = <abstr>
# S.value z;;
- : int = 30
# setx 50;;
- : unit = ()
# S.value z;;
- : int = 70
2
ответ дан 16 October 2019 в 23:39
поделиться

Вы можете имитировать это в Ruby:

x = 10
y = 20
z = lambda { x + y }
z.call    # => 30
z = 50
z.call    # => 70

Не совсем то, что вы хотите, но довольно близко.

0
ответ дан 16 October 2019 в 23:39
поделиться

JavaFX сделает это за вас, если вы используете bind вместо = для Z

2
ответ дан 16 October 2019 в 23:39
поделиться

Этот код на F# должен помочь. Вы можете использовать ленивую оценку (объект System.Lazy), чтобы гарантировать, что ваше выражение будет оценено, когда это действительно необходимо, а не раньше.

let mutable x = 10;
let y = 20;

let z = lazy (x + y);
x <- 30;

printf "%d" z.Value
-1
ответ дан 16 October 2019 в 23:39
поделиться

Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio

x = 10
y = 20
z = function () return x + y; конец
х = 50
= z ()
70

0
ответ дан 16 October 2019 в 23:39
поделиться

Вы можете найти это видео (с сайта Commercial Users of Functional Programming) интересным и достойным просмотра. Если у вас есть пользователи, страдающие технофобией, это может быть хорошим подходом для вас.

0
ответ дан 16 October 2019 в 23:39
поделиться

не уверен, насколько хорошо метапост (1) подойдет для вашего приложения, но он декларативен.

0
ответ дан 16 October 2019 в 23:39
поделиться

Вы можете сделать это в Tcl, в некоторой степени. В Tcl вы можете установить отслеживание переменной таким образом, что при каждом обращении к ней будет вызываться процедура. Эта процедура может пересчитать значение на лету.

Ниже приведен рабочий пример, который делает более или менее то, что вы просите:

proc main {} {
    set x 10
    set y 20
    define z {$x + $y}

    puts "z (x=$x): $z"
    set x 50
    puts "z (x=$x): $z"
}


proc define {name formula} {
    global cache
    set cache($name) $formula
    uplevel trace add variable $name read compute
}

proc compute {name _ op} {
    global cache
    upvar $name var
    if {[info exists cache($name)]} {
        set expr $cache($name)
    } else {
        set expr $var
    }
    set var [uplevel expr $expr]
}

main
1
ответ дан 16 October 2019 в 23:39
поделиться

Желание иметь два определения X является по своей сути императивным. В истинно декларативном языке у вас есть одно определение переменной в одной области видимости. Поведение, которого вы хотите от Excel, соответствует редактированию программы.

5
ответ дан 16 October 2019 в 23:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: