Подтвердить что ты не робот

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

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

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

Нижеприведенный код, очевидно, будет работать на С#, но это всего лишь код для задания, я ищу что-то немного больше, не говоря уже о том, что "технический шум"

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

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());

Итак, эквивалент синтаксиса ? -rerefix - это () -suffix, но в остальном он идентичен. Лямбда - это "формула" в вашей терминологии.

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

x = 10
y = 10

z = lambda: x + y

# Output: 20
print z()

x = 20

# Output: 30
print z()

Ответ 7

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

Ответ 9

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

Ответ 10

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

Ответ 11

Вы можете сделать это в 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

Ответ 12

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)

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

Ответ 13

В F # несколько словесно:

let x = ref 10
let y = ref 20

let z () = !x + !y

z();;
y <- 40
z();;

Ответ 14

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

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

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

Ответ 16

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

Ответ 17

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

x = 10
y = 20
z = функция() возвращает x + y; конец
x = 50
= z()
70

Ответ 18

Это не то, что вы ищете, но аппаратные описания Языки по определению являются "декларативными".

Ответ 19

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

let mutable x = 10;
let y = 20;

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

printf "%d" z.Value