From: Sean P. <sp...@ad...> - 2009-05-09 00:45:53
|
[sorry for the ugly quoting - struggling with webmail for a bit.] >>> I'm struggling with this, but let me see if I have this down. It seems like a relate clause requires all variables inside of it to be infinitely recursive. For example, if I have 4 variables in my relate clause, then each variable must have a define expression that uses the other 3. So I couldn't do something like this: relate { a <== b + 1 b <== a } Correct? <<< You could say that (with semi-colons) - but I don't know what the relationship means. Normally the functions are some form of an inverse of the other functions - so if you wanted to express "a = b + 1" it would be: relate { a <== b + 1; b <== a - 1; } >>> In the above example, if 'a' is prioritized because 'b' changed, then the value of 'b' will be 'out of date', because B should always equal A. In order for the above to be true, you would have to change 'b', have the relate clause update 'a' (because 'b' changed), and then it would have to update 'b' again with the new value of a (which should be one greater than its previous value). <<< Your example restated in english would be "there is a relationship between a and be which is satisfied if a = b + 1 or a = b" >>> I'm also assuming you *must* use define expressions in a relate clause. I don't see the point of using initializers, like this: relate { a : 90; b : 40; } <<< That would be a syntax error. Yes - you must use define expressions. >>> I think if you gave me a more practical example then I would understand the purpose of the relate clause. So far we've been giving overly simple logical examples, but I've not really seen a case where it makes sense to use a relate clause. It would help to see a case that would otherwise not be possible to implement without the existence of the relate clause. <<< Generally what you describe in a sheet are the arguments to some function (or command) which are being represented in the UI. You build a model of the function, capturing the pre-condition to the function (so the user can't invoke the function with bad arguments), you can also model properties of the post condition, so the user can describe the desired result (I want my compressed file to fit on a CD, you figure out the compression ratio), and values which are defined in terms of the argument (for example, a function takes a "force" argument, the definition of force is force = mass * acceleration, so you can model this definition and the user can then provide the force argument directly, or in terms of mass and acceleration). The relationship "width_in_inches = width_in_pixels / pixels_per_inch" is expressed as: relate { width_in_inches <== width_in_pixels / pixels_per_inch; pixels_per_inch <== width_in_pixels / width_in_inches; width_in_pixels <== width_in_inches * pixels_per_inch; } You could attach a UI to this with 3 numbers, edit any two and the third is derived. If the resolution where fixed, then simply drop the second term in the relationship. Then you have a two way relationship between width_in_inches and width_in_pixels. The most common relationships are just linear scalings of each other. The example with rotation (a,b and x,y) was developed as an example of how to express relationships between different colorspaces (RGB, CMYK, Lab, etc...). Let's say you want to write a video compression app and you want to build a UI to express all the dials, you might let the user select a desired final size, a frame rate, a frame size, video length, and a compression ration. If you can write the expressions to relate these variables, then you can specify the relate clause and attach your UI to it. Let's say we only let the user adjust the compression ratio or the final size. The relationship might be: relate { final_size <== frame_rate * frame_size * video_length * compression_ratio; compression_ratio <== final_size / (frame_rate * frame_size * video_length); } Often times you end up with relate clauses that overlap. For example, in the image size example you have width and hight related to a percentage of the original document width and height, and you have a conditional relation to constrain proportions which ensures that these percentages are equal - so you have: relate { width_percent <== width / width_original; width <== width_percent * width_original; } relate { height_percent <== height / height_original; height<== height_percent * height_original; } when (constrain) relate { height_percent <== width_percent; width_percent <== height_percent; } I hope those examples help... Sean |