Действительно декларативный язык? - PullRequest
21 голосов
/ 07 июня 2010

Кто-нибудь знает действительно декларативный язык? Мне нужно поведение, похожее на то, что делает 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. Это правильно с точки зрения императива, но я ищу более упрямое поведение, если вы понимаете, о чем я.

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

Приведенный ниже код, очевидно, будет работать на 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), которое делает это? Возможно, я не делаю это правильно в упомянутых языках или я полностью пропустил приложение, которое делает именно это.

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

Ответы [ 19 ]

17 голосов
15 голосов
/ 07 июня 2010

Похоже, вы просто хотите, чтобы 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());

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

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

9 голосов
/ 07 июня 2010

В 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).Первое связывает неоцененное выражение с переменной, второе связывает оцененное выражение .

5 голосов
/ 07 июня 2010

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

3 голосов
/ 07 июня 2010

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

x = 10
y = 10

z = lambda: x + y

# Output: 20
print z()

x = 20

# Output: 30
print z()
3 голосов
/ 07 июня 2010

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

2 голосов
/ 08 июня 2010

реаги - это библиотека 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 голосов
/ 07 июня 2010

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

2 голосов
/ 07 июня 2010

Существует библиотека Lisp с таким поведением:

http://common -lisp.net / проект / клетки /

2 голосов
/ 07 июня 2010

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

...