简体   繁体   中英

Does a programming language with the following features exist?

Is there a language which will support the following concept or is there a pattern to achieve something similar with existing one?

Concept

I want to define a Rectangle with the following properties: Length , Height , Area , Perimeter ; where Area = Length * Height and Perimeter = (2 * Length) + (2 * Height) .

Given the statement above, if I want to create a Rectangle by giving it a Length and a Height , it should of course automatically fill out the rest of the properties.

However, it should go further and automatically allow you to create a Rectangle with any two properties (say Height and Perimeter ) because that is also mathematically enough to create the same Rectangle .

Example

To help explain the idea, take this example:

//Declaration
Rectangle
{
    Height, Length, Area, Perimeter;

    Area = Height * Length;
    Perimeter = (2 * Length) + (2 * Height);
}

//Usage
main()
{
    var rectangleA = new Rectangle(Height, Length);
    var rectangleB = new Rectangle(Height, Area);

    Assert(rectangleA == rectangleB);
}

Notice how I didn't need to define constructors for Rectangle . Notice I did not need specify the specific logic needed if a Rectangle was created using Height and Area .

Edit: Should be rectangle and not a square for a proper example.

What you are looking for is a language with an integrated computer algebra system. It has to be able to resolve equations with respect to different variables.

While it would be possible to implement something like this, I doubt that it would make sense because in many cases there will be either no solution or multiple solutions.

Even your simple example will not work if only area and perimeter are given because there will usually be two solutions. (I assume that your class actually represents a rectangle and not a square, otherwise you should not have separate variables for length and height.)

Example:

Input: area = 2, perimeter = 6
Solution 1: length = 2, height = 1
Solution 2: length = 1, height = 2

Another remark not really related to your question: Your class obviously contains redundant member variables. This is a bad thing for various reasons, the most important being the possibility of inconsistencies. Unless you have very strict performance constraints, you should store only two of them, say length and width, and provide methods to calculate the others when needed.

Of course such a language exists. Many do, as you've now pointed out in your own comment to this answer.

In the example below I'll be using the Powerloom representation system, implemented in a language called STELLA . You can play with it from within a Common Lisp environment. Once you have everything installed you can load the language by running:

(cl:load "load-powerloom.lisp")
(in-package "STELLA")
(in-dialect "KIF")

That's about all you need to start building awesome geometrical objects. Within STELLA you may define a concept with the primitive defconcept :

(defconcept Rectangle (?r)
  :documentation "Curious geometrical objects that live on a plane.")

And define its properties with deffunction :

(deffunction rect-height ((?t Rectangle)) :-> (?n INTEGER))
(deffunction rect-length ((?t Rectangle)) :-> (?n INTEGER))
(deffunction area ((?t Rectangle)) :-> (?n INTEGER))
(deffunction perimeter ((?t Rectangle)) :-> (?n INTEGER))

To make the relations between area, perimeter and the sides of your rectangle, you'll have to make some assertions. That's what you'll have assert for.

(assert (forall (?t Rectangle)
                (= (area ?t) (* (rect-height ?t) (rect-length ?t)))))
(assert (forall (?t Rectangle)
                (= (perimeter ?t) (+ (* 2 (rect-height ?t))
                                     (* 2 (rect-length ?t))))))

You are telling STELLA that for all rectangles, the area is the product of height and length, and that for all rectangles, the perimeter is twice the height plus twice the length.

Now you can instantiate your objects, and it doesn't matter what properties you give it, as long as they make sense.

(definstance rect1 :Rectangle true :rect-height 10 :rect-length 10)
(definstance rect2 :Rectangle true :area 40 :rect-height 20)

Here you instantiate rect1 with height and length as parameters, and rect2 with area and height.

But its always good to check that the language is doing what you expect:

STELLA> (retrieve all ?x (= (area rect1) ?x))
There is 1 solution:
  #1: ?X=100

STELLA> (retrieve all ?x (= (rect-length rect2) ?x))
There is 1 solution:
  #1: ?X=2

If you ever get tired of rectangles and decide to build a beautiful square, why not derive a concept?

(defconcept Square ((?r Rectangle))
  :documentation "Weird rectangles that fascinated the Greeks"
  :<=> (= (rect-height ?r) (rect-length ?r)))

Simply tell STELLA that squares are rectangles where height and length are equal.

Now try it out:

STELLA> (definstance nice-rectangle :Rectangle true :rect-length 10 :area 100)
|i|NICE-RECTANGLE
STELLA> (ask (Square nice-rectangle))
TRUE

I'm not an expert at all, but I find the language fascinating. It's sad that there is so little information about it on the internet. Even the manual is incomplete. For more information I'd suggest starting with these slides .

The famous book SICP teaches how to build a nondeterministic evaluator for such a language here. And finally, a wonderful write up describing motivations and applications behind these ideas can be seen here .

In C#, you can use properties, which have implicit getters and setters. That way you can write something like:

public class Square {
    public int Length {
        get { return length; }
        set { length = value; }
    }
    public int Area {
        get { return length * length; }
        set { length = Math.Sqrt(value); }
    }
    public int Perimeter {
        get { return length * 4; }
        set { length = value / 4; }
    }
    private int length;
}

Now you can write:

Square square = new Square();
square.Length = 2;
Console.WriteLine(square.Length);    // "2"
Console.WriteLine(square.Area);      // "4"
Console.WriteLine(square.Perimeter); // "8"
square.Area = 9;
Console.WriteLine(square.Length);    // "3"
Console.WriteLine(square.Area);      // "9"
Console.WriteLine(square.Perimeter); // "12"

Edit:

C# also allows you name properties at your choosing when instantiating an object:

Square square1 = new Square { Perimeter = 12 };
Square square2 = new Square { Length = 4 };

I don't think something like this does exist in the form of a programming language.

Ontology

However the first approach I can think about is defining an Ontology, I mean a set of rules about

  1. Entities: Rectangle, Square, Dog, Car, etc...
  2. Attributes: Area, Height, Number of Wheels, etc...
  3. Relations between (1) and (2): Rectangle's Area is Height * Width, ...

Now given a list of attributes and the required output Entity

I have height and width and I need a Rectangle

the system could search for a path through the rules graph to produce the required outcome based on the provided inputs.

Real world example

Wolfram Alpha probably follows the technique described above

在此输入图像描述

在此输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM