21

Does anyone know of a truly declarative language? The behavior I'm looking for is kind of what Excel does, where I can define variables and formulas, and have the formula's result change when the input changes (without having set the answer again myself)

The behavior I'm looking for is best shown with this pseudo code:

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)

I've tried this in a lot of languages like F#, python, matlab etc, but every time I tried this they come up with 30 instead of 70. Which is correct from an imperative point of view, but I'm looking for a more declarative behavior if you know what I mean.

And this is just a very simple calculation. When things get more difficult it should handle stuff like recursion and memoization automagically.

The code below would obviously work in C# but it's just so much code for the job, I'm looking for something a bit more to the point without all that 'technical noise'

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!
}

This just seems like so much code, curly braces and semicolons that add nothing.

Is there a language/ application (apart from Excel) that does this? Maybe I'm no doing it right in the mentioned languages, or I've completely missed an app that does just this.

I prototyped a language/ application that does this (along with some other stuff) and am thinking of productizing it. I just can't believe it's not there yet. Don't want to waste my time.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
gjvdkamp
  • 9,929
  • 3
  • 38
  • 46
  • 15
    You want to look for reactive programming languages (or frameworks), not "declarative" ones. – Deniz Dogan Jun 07 '10 at 15:27
  • 6
    Prolog? http://en.wikipedia.org/wiki/Prolog – Blorgbeard Jun 07 '10 at 15:30
  • Lots of interesting ideas from different areas in this thread. – Mau Jun 07 '10 at 16:10
  • 1
    Is it bad if my first thought was Microsoft Excel? – zildjohn01 Jun 07 '10 at 16:35
  • Unfortunately my language, Continuous Programming, isn't finished yet :-( It's like this but then better. And like Deniz said; it's indeed called (functional?) reactive programming. – Pindatjuh Jun 07 '10 at 17:19
  • Excel still is the bomb when it comes to simplicity, but in my real world problems it just crumbles (multi user, version control, managing change on large models with data in it, collaborating on the modelling etc. So much not adressed when you try to use Excel on a large scale. – gjvdkamp Jun 07 '10 at 17:54
  • 1
    Wow I totally missed the field of reactive programming, thanks a LOT. Seems like i reinvented a few conecepts from that.. (>_<) I will defenitely read up on it. Maybe I'm just splitting hairs here, but I think reactive programming and declarative programming are about the same topic. In that reactive programming relates to declarative programming like an engine relates to a car. Reactive programming would be the mechanism that allows a language to be declarative. – gjvdkamp Jun 07 '10 at 18:03
  • For the rest of you, this page on WIkipedia is pretty awesome, especially the index on the right hand side. http://en.wikipedia.org/wiki/Programming_paradigm – gjvdkamp Jun 07 '10 at 18:33

18 Answers18

17

Any Constraint Programming system will do that for you. Examples of CP systems that have an associated language are ECLiPSe, SICSTUS Prolog / CP package, Comet, MiniZinc, ...

Mau
  • 14,234
  • 2
  • 31
  • 52
15

It looks like you just want to make Z store a function instead of a value. In 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());

So the equivalent of your ?-prefix syntax is a ()-suffix, but otherwise it's identical. A lambda is a "formula" in your terminology.

Behind the scenes, the C# compiler builds almost exactly what you presented in your C# conceptual example: it makes X into a field in a compiler-generated class, and allocates an instance of that class when the code block is entered. So congratulations, you have re-discovered lambdas! :)

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • 2
    Hmmm... I understand what you're proposing here and this already is the most upvoted answer... but I don't think this answer follows the spirit of the question. The necessity of the parentheses() bolted on to the Z identifier and the lambda is simply another syntax workaround. I think his question is more about asking if there's a language with a "runtime" that elegantly manages a chain of dependencies behind each variable while also intelligently detecting circular references --- basically he's asking for Excel without the UI. – JasDev Jun 07 '10 at 17:21
  • Sweet, but i agree that there are still quite a few concepts the user would have to master before he/ she could come up with somehting like this. It's not as to the point as, well, Excel. Nothing seems to be, all other languages seem to be by geeks, for geeks. With a lot of 'funny' characters – gjvdkamp Jun 07 '10 at 17:57
  • Actually I'm asking for Excel, with the GUI, but with a lot of other tools that will let me build much larger models than you can with Excel. And above all more structure. Building larger models just gets too tedious and error prone with excel. – gjvdkamp Jun 07 '10 at 18:00
9

In Mathematica, you can do this:

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 *)

The operator := (SetDelayed) is different from = (Set). The former binds an unevaluated expression to a variable, the latter binds an evaluated expression.

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • Ok I hadn't seen mathemaica yet, pfft more homework ;-) Although I'm afraid that Mathematica would be too 'scary' for business users. Thanks! – gjvdkamp Jun 07 '10 at 18:10
5

Wanting to have two definitions of X is inherently imperative. In a truly declarative language you have a single definition of a variable in a single scope. The behavior you want from Excel corresponds to editing the program.

Norman Ramsey
  • 198,648
  • 61
  • 360
  • 533
  • Hmm.. had to think about this for a second but I don't think i agree. (Wikipedia doesn't seem to either: http://en.wikipedia.org/wiki/Declarative_programming). I think you're mixing up immutability and functional programming with declarative. They're close, but different. GJ – gjvdkamp Jun 07 '10 at 19:08
  • 5
    Not that I believe anything I read on Wikipedia, but Wikipedia says "no control flow". Multiple assignments to X require control flow---one has to come before the other. – Norman Ramsey Jun 08 '10 at 01:18
3

Have you seen Resolver One? It's like Excel with a real programming language behind it.

Craig Stuntz
  • 125,891
  • 12
  • 252
  • 273
  • I Yeah I saw that quite a while ago, I'll look at it again – gjvdkamp Jun 07 '10 at 17:40
  • Hi, I just downloaded it. Seems pretty nifty in that it educates the user in python while the user can do the stuff he's used to up top. But i'm afraid that the code below will scare the s**t out of business users... will looking further into it though, thanks! – gjvdkamp Jun 07 '10 at 18:23
  • 2
    @gjv: Business users are so easy to be scared ;) – kennytm Jun 09 '10 at 13:42
  • True true, but seeing programmers struggle with semi-structured problems is just as funny. Let's write something to bridge this gap. – gjvdkamp Jun 13 '10 at 18:59
3

Here is Daniel's example in Python, since I noticed you said you tried it in Python.

x = 10
y = 10

z = lambda: x + y

# Output: 20
print z()

x = 20

# Output: 30
print z()
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
Wayne Werner
  • 49,299
  • 29
  • 200
  • 290
  • Thanks, but this Lambda stuff would be too much for the simpletons I have in mind. It distracts from the original problem, it's what I call technical noise. It seems that every language I've seen so for has this. – gjvdkamp Jun 07 '10 at 18:11
2

Two things you can look at are the cells lisp library, and the Modelica dynamic modelling language, both of which have relation/equation capabilities.

Pete Kirkham
  • 48,893
  • 5
  • 92
  • 171
2

There is a Lisp library with this sort of behaviour:

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

SK-logic
  • 9,605
  • 1
  • 23
  • 35
2

JavaFX will do that for you if you use bind instead of = for Z

Ma99uS
  • 10,605
  • 8
  • 32
  • 42
2

react is an OCaml frp library. Contrary to naive emulations with closures it will recalculate values only when needed

        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
ygrek
  • 6,656
  • 22
  • 29
1

You can do this in Tcl, somewhat. In tcl you can set a trace on a variable such that whenever it is accessed a procedure can be invoked. That procedure can recalculate the value on the fly.

Following is a working example that does more or less what you ask:

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
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I know a lot of languages, from assembly to java / c#. But this Tcl syntax seams giberrish :) – Marino Šimić Jun 29 '11 at 10:27
  • @Marino Šimić: I think it's easier to learn Tcl if you don't know too many other languages. Tcl is different, and requires that you suspend some of your assumptions about how a language should work. The real beauty of Tcl is not in its syntax, but in its lack of syntax. Admittedly, though, this is not a particularly good example of Tcl; it's a bit contrived, showing an edge case almost no-one would use. – Bryan Oakley Jun 29 '11 at 11:22
0

Groovy and the magic of closures.

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)

It's possible to add automagic memoization to functions too but it's a lot more complex than just one or two lines. http://blog.dinkla.net/?p=10

Trevor Tippins
  • 2,827
  • 14
  • 10
0

In F#, a little verbosily:

let x = ref 10
let y = ref 20

let z () = !x + !y

z();;
y <- 40
z();;
Mau
  • 14,234
  • 2
  • 31
  • 52
  • Ok thanks! That's the beaviour I want, but I'm afraid the syntax is going to throw business users off. I'm trying 'not to make them think' Any special character like !{}; etc should go. Forget any off them once and the answer will be correct until you change an input. Too dangerous, those are nasty bugs to spot for noobs. I'm really targeting business users here. – gjvdkamp Jun 07 '10 at 17:46
0

You can mimic it in Ruby:

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

Not quite the same as what you want, but pretty close.

mipadi
  • 398,885
  • 90
  • 523
  • 479
0

not sure how well metapost (1) would work for your application, but it is declarative.

vlabrecque
  • 346
  • 1
  • 4
0

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

x = 10
y = 20
z = function() return x + y; end
x = 50
= z()
70

  • Hi, thanks! Lua seems to go in that direction but still, i want somehting that defaults to this behaviour and does not allow for a wrong answer to come out. Having function() as opt in behaviour and omitting that doing an immediate assignment is not good enough. It would make people think too much. Thanks anyway, lookng at Parrot now beacuase that's below a lot of these langauges. So far Excel seems to be the only one... weird, but useful. – gjvdkamp Jun 13 '10 at 18:56
-1

It's not what you're looking for, but Hardware Description Languages are, by definition, "declarative".

rlbond
  • 65,341
  • 56
  • 178
  • 228
-1

This F# code should do the trick. You can use lazy evaluation (System.Lazy object) to ensure your expression will be evaluated when actually needed, not sooner.

let mutable x = 10;
let y = 20;

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

printf "%d" z.Value
Martin Jonáš
  • 2,309
  • 15
  • 12