POV-Ray : Newsgroups : povray.pov4.discussion.general : POV-Ray 4 SDL: Some concrete proposal Server Time
18 Apr 2024 17:25:28 EDT (-0400)
  POV-Ray 4 SDL: Some concrete proposal (Message 1 to 10 of 27)  
Goto Latest 10 Messages Next 10 Messages >>>
From: clipka
Subject: POV-Ray 4 SDL: Some concrete proposal
Date: 13 Apr 2009 16:00:00
Message: <web.49e39942d93ad1dd2dae03a10@news.povray.org>
I'll try to describe what I have currently in mind. But first let me present to
you a kind of "hello world" scene written in that language:


include "colors.inc";

SphereCenter = <0,1,0>;

sphere {
  center: SphereCenter;
  radius: 1 as SphereRadius;
  texture {
    pigment { color: #<1,0,0> }
  };
} as MainSphere;

plane {
  normal: <1,1,0>;
  offset: SphereRadius;
  translate(SphereCenter);
  texture {
    pigment { color: #<0,1,0> };
  };
};

for I = 1 to 100 do
  sphere {
    radius: 0.1;
    center: y * SphereRadius;
    rotate((x * rand() as local R1 * 2 * pi), (y * rand() * 2 * pi));
    texture {
      pigment { color: #<0,0,R1> };
    };
  };
end;

modify MainSphere {
  radius: 0.9;
};

MainSphere {
  center: .center + y*0.5;
};

debug(MainSphere.center);
debug(MainSphere["center"]);


Some things about the basic formalism:

- There is always a "current object"

- Expressions by themselves constitute a statement basically saying "apply this
to the current object in the manner making most sense" (the definition of which
is up to that object).

- "sphere{...}" is an expression returning a sphere. As a matter of fact, it is
an expression taking a "prototype" object (in this case *the* prototype sphere)
and a "modification block" describing how the desired object differs from that
prototype. (Similarly, "MainSphere{...}" takes MainSphere as a prototype to
build yet another one.) Within that modification block, the newly created
object is the current one.

- "rotate(...) and translate()" are functions both returning a transformation;
as an expression-only statement, these transformations are applied to the
current object (which hopefully knows what to do with them).

- "modify MainSphere{...}" is a statement taking a "modification block" as well,
in this case describing how the object itself is to be changed.

- adding "as <Name>" to an expression stores the value of that expression for
later use, serving as an "on-the-fly assignment"

- variables are global by default when assigned; in expressions, local variables
take precedence. Local variables are visible only in the code block in which
they are used (in case of the "R1" variable, this is the enclosing for loop)

- the current object's properties are assigned to using "<Name>: <Value>" to
avoid mixups with local and global variables

- the current object's properties can also be accessed using ".<Name>"; note
that this also allows for ".<Name> = <Value>", but using so makes the code ugly
as it optically disrupts indentation ;)

- "MainSphere["center"]" and "MainSphere.center" are equivalent notation. Only
works with strings conforming to identifier rules of course.

- the language will ultimately provide means to roll your own objects (thereby
allowing to create very powerful "macros")


Post a reply to this message

From: Warp
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 13 Apr 2009 16:23:21
Message: <49e39f38@news.povray.org>
clipka <nomail@nomail> wrote:
> SphereCenter = <0,1,0>;

> sphere {
>   center: SphereCenter;
>   radius: 1 as SphereRadius;
>   texture {
>     pigment { color: #<1,0,0> }
>   };
> } as MainSphere;

  I find that rather inconsistent.

  First you use "name = value" to define a vector, but then you use
"value as name" to define an object.

  What's wrong with using "MainSphere = sphere { ... };"? That would make
it consistent and closer to the current SDL. You also save a useless
reserved keyword.

> modify MainSphere {
>   radius: 0.9;
> };

  I'm not sure about that syntax, but IMO it should be at least in addition
to a syntax like:

MainSphere.radius = 0.9;

  The dot syntax is intuitive from many languages (including the current
SDL itself), and can be used as an lvalue and an rvalue, an example of the
latter being:

theRadius = MainSphere.radius;

-- 
                                                          - Warp


Post a reply to this message

From: clipka
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 13 Apr 2009 16:40:00
Message: <web.49e3a2023a7e550e2dae03a10@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
> > SphereCenter = <0,1,0>;
>
> > sphere {
> >   center: SphereCenter;
> >   radius: 1 as SphereRadius;
> >   texture {
> >     pigment { color: #<1,0,0> }
> >   };
> > } as MainSphere;
>
>   I find that rather inconsistent.
>
>   First you use "name = value" to define a vector, but then you use
> "value as name" to define an object.
>
>   What's wrong with using "MainSphere = sphere { ... };"? That would make
> it consistent and closer to the current SDL. You also save a useless
> reserved keyword.

Nothing - I jsut wanted to show two different ways of doing things. Probably
dind't make it plain enough.

Both the following would be valid statements:

  MainSphere = sphere { ... };
  sphere { ... } as MainSphere;

with the difference that the former would not automatically add it to the scene,
just create a prototype.

> > modify MainSphere {
> >   radius: 0.9;
> > };
>
>   I'm not sure about that syntax, but IMO it should be at least in addition
> to a syntax like:
>
> MainSphere.radius = 0.9;
>
>   The dot syntax is intuitive from many languages (including the current
> SDL itself), and can be used as an lvalue and an rvalue, an example of the
> latter being:

Um... where in the current SDL is that notation used? I mean, other than vector
(and color vector) components?

N.B. That syntax would also be available; however, the "modify" type of notation
would allow for a more concise tampering with multiple values of a single
object.

I'd find it inconsistent to be able to modify a freshly created object in such a
way, but not an existing one.


Post a reply to this message

From: Lukas Winter
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 13 Apr 2009 17:40:40
Message: <49e3b158$1@news.povray.org>
Am Mon, 13 Apr 2009 15:57:54 -0400 schrieb clipka:
> - "sphere{...}" is an expression returning a sphere. As a matter of
> fact, it is an expression taking a "prototype" object (in this case
> *the* prototype sphere) and a "modification block" describing how the
> desired object differs from that prototype. (Similarly,
> "MainSphere{...}" takes MainSphere as a prototype to build yet another
> one.) Within that modification block, the newly created object is the
> current one.

Prototyping is a great concept and I'd love to see it in POV 4.

> - "rotate(...) and translate()" are functions both returning a
> transformation; as an expression-only statement, these transformations
> are applied to the current object (which hopefully knows what to do with
> them).

I find this inconsistent. Why is rotate a function and sphere is not a 
function? I think rotate and translate should be expressions returning a 
transformation and use curly brackets as well. They could return identity 
transformations as a default. Ultimately I dream of foing something like 
this:

/*let's define the prototype of a rotation around a certain axis...*/
rotate_around_axis = rotate
{
  input axis = #<1, 0, 0>; /*default value*/
  input amount = 0; /*default value*/
  rotation_vector = /*whatever it takes to calculate this rotation*/;
};

/*let's use it!*/
sphere
{
  radius = 20;
  center = <100, 0, 0>;
  transformation *= rotate_around_axis
    {
      axis = <.5, .5, .5>;
      amount = 30;
      /*the actual transformation is automagically performed according to 
the calculations made in the definition of rotate_around_axis.*/
    };
};

Which means: lazy evaluation of prototype definitions! I chose = instead 
of : because of consistency and *= means composition of two 
transformation and writing the result back to the lhs. Simply putting a 
transformation inside a modification block does not work for me (it works 
in POV 3 because it does not use object properties). There should be 
something to signify that you are _applying_ this transformation.

> 
> - "modify MainSphere{...}" is a statement taking a "modification block"
> as well, in this case describing how the object itself is to be changed.
> 
I'm pretty sure we don't need modify. Just use

MainSphere = MainSphere
{
  radius = NewRadiusForMainSphere
};

This should be the same. We're just using a variable as the prototype for 
itself, clever, huh? ;)

> - adding "as <Name>" to an expression stores the value of that
> expression for later use, serving as an "on-the-fly assignment"

I agree with Warp here, a = would be more consistent.

> - variables are global by default when assigned; in expressions, local
> variables take precedence. Local variables are visible only in the code
> block in which they are used (in case of the "R1" variable, this is the
> enclosing for loop)

> - the current object's properties are assigned to using "<Name>:
> <Value>" to avoid mixups with local and global variables

> - the current object's properties can also be accessed using ".<Name>";
> note that this also allows for ".<Name> = <Value>", but using so makes
> the code ugly as it optically disrupts indentation ;)

You mean "<Name> : <Value>" is shorthand for ".<Name> = <Value>"? I'd 
rather make "::<Name>" access a global variable and "<Name>" always 
access the most local one, like in C++. So we'd get rid of all those 
different notations for assigning variables.

So, here's my version of your example ;)

include "colors.inc";

SphereCenter = <0,1,0>;

MainSphere = sphere {
  center = SphereCenter;
  radius = 1;
  ::SphereRadius = radius; //if you _really_ want to create this global 
variable
  texture = texture
  {
    /*Local texture overrides global texture but that's no problem because
    the prototype already has a default texture.*/
    pigment { color = <1,0,0> }
  };
};

scene += MainSphere; /*or whatever symbol is reserved for "append"*/

scene += plane {
  normal = <1,1,0>;
  offset = SphereRadius;
  transformation *= translate{offset = SphereCenter}; /*Probably too 
verbose...*/
  texture = texture {
    pigment = pigment { color = <0,1,0> };
  };
};

gen = random_generator
{
  seed = 12345;
}

/*I'm not sure whether I like this syntax or not...*/
for I = 1 to 100 do
  scene += sphere {
    radius = 0.1;
    center = y * SphereRadius;
    R1 = gen.rand();
    transformation *= rotate{ radians = x * R1 * 2 * pi; }
                    * rotate{ degrees = y * gen.rand() * 2 * 360;};  
    texture = texture {
      pigment = pigment { color = <0,0,R1> };
    };
  };
end;

MainSphere = MainSphere {
  radius = 0.9;
};
/*Do we modify what was already added to the scene? Then we can't clone 
objects this way! If we don't, we can't change objects that are already 
in the scene! Note that the "modify" keyword is no solution to that 
problem.*/

scene += MainSphere {
  center = center + y*0.5;
};

/*Here I think the intention here was to clone MainSphere.*/

debug(MainSphere.center);
debug(MainSphere["center"]);

Ah, sorry for taking your nice syntax apart and transforming it to 
something completely different. I just couldn't resist. I think you're on 
the right track, though!


Post a reply to this message

From: clipka
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 13 Apr 2009 19:00:00
Message: <web.49e3c2da3a7e550e2dae03a10@news.povray.org>
Lukas Winter <web### [at] geloeschtremovethisandthedotbeforenet> wrote:
> Prototyping is a great concept and I'd love to see it in POV 4.

Yes, I think it's a powerful thing. It doesn't allow for as good a type checking
as class or interface based concepts, but it has the tremendous advantage of
coming at very low overhead and very high flexibility.

> > - "rotate(...) and translate()" are functions both returning a
> > transformation; as an expression-only statement, these transformations
> > are applied to the current object (which hopefully knows what to do with
> > them).
>
> I find this inconsistent. Why is rotate a function and sphere is not a
> function? I think rotate and translate should be expressions returning a
> transformation and use curly brackets as well. They could return identity
> transformations as a default.

Well, both approaches would be ok in this language framework; it would be a
matter of definition.

I think however that the function-based approach is better, because it would
define transformations as basically property-less. So nobody tries to do things
like:

  sphere {
    rotate { axis: <1,0,0>; angle: 30 deg; } as myRotate;
    translate { vector: <1,2,3>; };
  }
  myRotate.angle = 60 deg;

Otherwise, POV-Ray would need to keep track of a stack of transformations
applied to the object (and similarly all the texture patterns and such as
well), just in case someone would want to modify one of the steps later.

> Ultimately I dream of foing something like this:

> /*let's define the prototype of a rotation around a certain axis...*/
> rotate_around_axis = rotate
> {
>   input axis = #<1, 0, 0>; /*default value*/
>   input amount = 0; /*default value*/
>   rotation_vector = /*whatever it takes to calculate this rotation*/;
> };
>
> /*let's use it!*/
> sphere
> {
>   radius = 20;
>   center = <100, 0, 0>;
>   transformation *= rotate_around_axis
>     {
>       axis = <.5, .5, .5>;
>       amount = 30;
>       /*the actual transformation is automagically performed according to
> the calculations made in the definition of rotate_around_axis.*/
>     };
> };
>
> Which means: lazy evaluation of prototype definitions!

This is definitely something we would want - but isn't lazy evaluation the
domain of functions?

Maybe we could get a consensus by allowing for named parameters in functions.

There should be, however, *some* distinction between the two in syntax (not only
in defining them, but also in using them), so it is clear to the user that it
makes no sense to try to manipulate the parameters of the function.

> I chose = instead
> of : because of consistency

> and *= means composition of two
> transformation and writing the result back to the lhs. Simply putting a
> transformation inside a modification block does not work for me (it works
> in POV 3 because it does not use object properties). There should be
> something to signify that you are _applying_ this transformation.

In the language concept I have in mind, it would simply be (taking the freedom
to make this a function again, albeit with named parameters):

sphere
{
  radius = 20;
  center = <100, 0, 0>;
  rotate_around_axis
  (
    axis = <.5, .5, .5>;
    amount = 30;
  );
};

because, as already mentioned in the original post, expressions by themselves
(whether they be from prototype-cloning or function-calling) are always
*applied*. Note that a sphere would "know what to do" with a transformation
being applied to it. Most importantly, it would know that it would have to
update its children accordingly, too. Which a simple tampering with the spere's
*own* transformation matrix wouldn't do.

(Granted, we'd probably want a way to allow for getter/setter methods anyway...)

> > - "modify MainSphere{...}" is a statement taking a "modification block"
> > as well, in this case describing how the object itself is to be changed.
> >
> I'm pretty sure we don't need modify. Just use
>
> MainSphere = MainSphere
> {
>   radius = NewRadiusForMainSphere
> };
>
> This should be the same. We're just using a variable as the prototype for
> itself, clever, huh? ;)

Duh. I've just started laying out the basics of the language, and people already
start exploiting its details :P

Note however that this might be slower on a non-optimizing interpreter: It would
have to copy the object first, then discard the original one.

It would also make a difference in case of:

MySphere = sphere {...};
MySphereAlias = MySphere; // no prototype instantiation here, just an alias!
modify MySphere {...};

(Then again, disallowing "modify" would prevent any misconception about how this
case would work out.)

> > - adding "as <Name>" to an expression stores the value of that
> > expression for later use, serving as an "on-the-fly assignment"
>
> I agree with Warp here, a = would be more consistent.

So how would you express such an "on-the-fly assignment" then?

> You mean "<Name> : <Value>" is shorthand for ".<Name> = <Value>"? I'd
> rather make "::<Name>" access a global variable and "<Name>" always
> access the most local one, like in C++. So we'd get rid of all those
> different notations for assigning variables.

The thing is, I don't like those interpunctuation prefixes: When you start lots
of statements with these, it messes up the indentation, optically speaking.

>
> So, here's my version of your example ;)
>
> include "colors.inc";
>
> SphereCenter = <0,1,0>;
>
> MainSphere = sphere {
>   center = SphereCenter;
>   radius = 1;
>   ::SphereRadius = radius; //if you _really_ want to create this global
> variable
>   texture = texture
>   {
>     /*Local texture overrides global texture but that's no problem because
>     the prototype already has a default texture.*/
>     pigment { color = <1,0,0> }
>   };
> };

> scene += MainSphere; /*or whatever symbol is reserved for "append"*/

I'd prefer to avoid this "scene +=" - I think it's unnecessary bulk. Similarly
with the "texture = texture" above.

> /*I'm not sure whether I like this syntax or not...*/

You mean the "for" loop? I find nothing wrong with it.
The remainder of the syntax, that's what you came up with yourself :P

> MainSphere = MainSphere {
>   radius = 0.9;
> };
> /*Do we modify what was already added to the scene? Then we can't clone
> objects this way!

Hm, yeah - you're making the point why I originally added the "modify" statement
in the first place, but I forgot about it :}

> If we don't, we can't change objects that are already
> in the scene! Note that the "modify" keyword is no solution to that
> problem.*/

Why isn't it? If the POV-Ray internals can cope with an object being modified,
then this shouldn't be an issue.

> scene += MainSphere {
>   center = center + y*0.5;
> };
>
> /*Here I think the intention here was to clone MainSphere.*/
>
> debug(MainSphere.center);
> debug(MainSphere["center"]);
>
> Ah, sorry for taking your nice syntax apart and transforming it to
> something completely different. I just couldn't resist. I think you're on
> the right track, though!

Yeah, basically. I'm quite sure about the underlying idea. I'm still struggling
with the details, like how to get a syntax that is both perfectly consistent
*and* looks good. Mostly the "center:..." vs. alternatives like "center=...",
".center=..." or some such doesn't yet satisfy me.

That, and your and Warp's objection against the "as" statement. I actually like
it, but your complaint regarding inconsistency has some justification, too.


Post a reply to this message

From: Lukas Winter
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 14 Apr 2009 08:19:02
Message: <49e47f36@news.povray.org>
Am Mon, 13 Apr 2009 18:55:22 -0400 schrieb clipka:

> 
> I think however that the function-based approach is better, because it
> would define transformations as basically property-less. So nobody tries
> to do things like:
> 
>   sphere {
>     rotate { axis: <1,0,0>; angle: 30 deg; } as myRotate; translate {
>     vector: <1,2,3>; };
>   }
>   myRotate.angle = 60 deg;
> 
> Otherwise, POV-Ray would need to keep track of a stack of
> transformations applied to the object (and similarly all the texture
> patterns and such as well), just in case someone would want to modify
> one of the steps later.

Well, I think the point here is: Do we store references in variables or 
actual copies of the data? If we store references, then yes, POV-Ray 
would need to keep track of them in its internal state. If we don't then 
"myRotate.angle = 60 deg" would do nothing until we use myRotate in an 
object modification block. Thats the same problem as cloning vs. 
modifying objects in the scene.

> 
> This is definitely something we would want - but isn't lazy evaluation
> the domain of functions?
> 
> Maybe we could get a consensus by allowing for named parameters in
> functions.
> 

Yeah, I thought of blurring the distinction between functions and 
prototypes. Sometimes named parametres are useful, sometimes they are not 
needed. We could allow both, we just need a syntax for it.

Let's sum up the classic differences between a function and an object:
A function has the type of its return value as soon as parametres are 
bound to it. As long as no parameters are bound to it it has a type 
determined by the number (and type) of its arguments. An object always 
has the type it was given when it was created.
A function has parameters which are distinguished by their order. An 
object has members or properties with names.

If we add input properties which delay calculation of other properties to 
our language then functions and prototypes can perform the same task with 
a different syntax. I'm not to happy with that, _one_ way to do things 
should be enough.

> There should be, however, *some* distinction between the two in syntax
> (not only in defining them, but also in using them), so it is clear to
> the user that it makes no sense to try to manipulate the parameters of
> the function.
> 
>> I chose = instead
>> of : because of consistency
> 
>> and *= means composition of two
>> transformation and writing the result back to the lhs. Simply putting a
>> transformation inside a modification block does not work for me (it
>> works in POV 3 because it does not use object properties). There should
>> be something to signify that you are _applying_ this transformation.
> 
> In the language concept I have in mind, it would simply be (taking the
> freedom to make this a function again, albeit with named parameters):
> 
> sphere
> {
>   radius = 20;
>   center = <100, 0, 0>;
>   rotate_around_axis
>   (
>     axis = <.5, .5, .5>;
>     amount = 30;
>   );
> };
> 
> because, as already mentioned in the original post, expressions by
> themselves (whether they be from prototype-cloning or function-calling)
> are always *applied*. Note that a sphere would "know what to do" with a
> transformation being applied to it. Most importantly, it would know that
> it would have to update its children accordingly, too. Which a simple
> tampering with the spere's *own* transformation matrix wouldn't do.
> 
> (Granted, we'd probably want a way to allow for getter/setter methods
> anyway...)

Hm, now I'm getting a understanding of what you are aiming for. Then an 
operator meaning "apply" would also be nice, wouldn't it?

perhaps
MyTransformedSphere = MySphere ~ MyTransform;


> 
> Duh. I've just started laying out the basics of the language, and people
> already start exploiting its details :P
> 
Exploitation of details makes a programming language powerful ;) 
Unfortunately that means paying attention to details when designing a 
language is very important.

> Note however that this might be slower on a non-optimizing interpreter:
> It would have to copy the object first, then discard the original one.

It should be trivial to recognize a pattern like
<something> = <somthing>
{
  /*something*/
}

> It would also make a difference in case of:
> 
> MySphere = sphere {...};
> MySphereAlias = MySphere; // no prototype instantiation here, just an
> alias! modify MySphere {...};
> 
> (Then again, disallowing "modify" would prevent any misconception about
> how this case would work out.)
> 

Again, reference vs copy.

> 
> So how would you express such an "on-the-fly assignment" then?

I don't. If I want to I assign first and then reuse the assigned variable.

> The thing is, I don't like those interpunctuation prefixes: When you
> start lots of statements with these, it messes up the indentation,
> optically speaking.
> 

I'm not sure what you mean with "messing up the indentation", but people 
are used to such prefixes. Just think of directory structures:

. is the current working directory
.. is the parent directory
/ is the top level directory

and so on.

> 
> I'd prefer to avoid this "scene +=" - I think it's unnecessary bulk.
> Similarly with the "texture = texture" above.
> 
I see what you mean. So objects apply themselves to the global object 
which is the scene itself?

> 
> You mean the "for" loop? I find nothing wrong with it. The remainder of
> the syntax, that's what you came up with yourself :P
> 

I mean for ... end. I always find using words to open and close blocks 
hard to read.

> 
> Hm, yeah - you're making the point why I originally added the "modify"
> statement in the first place, but I forgot about it :}
> 
>> If we don't, we can't change objects that are already in the scene!
>> Note that the "modify" keyword is no solution to that problem.*/
> 
> Why isn't it? If the POV-Ray internals can cope with an object being
> modified, then this shouldn't be an issue.

Then "as" creates a reference, "modify" modifies the target of a 
reference, "=" creates a copy, and what does "modify" do if the variable 
it should modify is not a reference...

> 
> Yeah, basically. I'm quite sure about the underlying idea. I'm still
> struggling with the details, like how to get a syntax that is both
> perfectly consistent *and* looks good. Mostly the "center:..." vs.
> alternatives like "center=...", ".center=..." or some such doesn't yet
> satisfy me.
> 
> That, and your and Warp's objection against the "as" statement. I
> actually like it, but your complaint regarding inconsistency has some
> justification, too.

I just want to prevent SDL 4 becoming cluttered with keywords like "as" 
and "modify" when there is a way to express the same thing in a concise 
manner without them. This may seem pedantic but SDL 3 is such a mess with 
keywords. When I started writing #macros I just wanted to call a variable 
"x"... guess what happened ;)


Post a reply to this message

From: MessyBlob
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 14 Apr 2009 08:55:00
Message: <web.49e486f13a7e550eaddfbead0@news.povray.org>
Lukas Winter <web### [at] geloeschtremovethisandthedotbeforenet> wrote:
> Am Mon, 13 Apr 2009 18:55:22 -0400 schrieb clipka:
>
> > I think however that the function-based approach is better, because it
> > would define transformations as basically property-less. So nobody tries
> > to do things like:
> >
> >   sphere {
> >     rotate { axis: <1,0,0>; angle: 30 deg; } as myRotate; translate {
> >     vector: <1,2,3>; };
> >   }
> >   myRotate.angle = 60 deg;
> >
> > Otherwise, POV-Ray would need to keep track of a stack of
> > transformations applied to the object (and similarly all the texture
> > patterns and such as well), just in case someone would want to modify
> > one of the steps later.
>
> Well, I think the point here is: Do we store references in variables or
> actual copies of the data? If we store references, then yes, POV-Ray
> would need to keep track of them in its internal state. If we don't then
> "myRotate.angle = 60 deg" would do nothing until we use myRotate in an
> object modification block. Thats the same problem as cloning vs.
> modifying objects in the scene.

You'd want a transformation for each container, which doesn't prevent references
being used. Those that seem to be a list of transformations interleaved with
effects would be processed into a nested structure, each having the
transformations and effects before the container is closed.

I think we can use the usual (simple) language constructs to create references,
and new declarations for copies.

Generally, we could go for partial OO implementation for the scene objects,
which means that we don't carry per-instance methods, but instead just have the
instances (with a single pointer) locate the methods for the class, along with
the enumerated properties. The parser would be version-matched to the engine,
which removes any opaque enumeration from the SDL source scripts.


Post a reply to this message

From: clipka
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 14 Apr 2009 10:40:00
Message: <web.49e49f1f3a7e550ef06ce2830@news.povray.org>
Lukas Winter <web### [at] geloeschtremovethisandthedotbeforenet> wrote:
> Well, I think the point here is: Do we store references in variables or
> actual copies of the data?

I think we'll want to store references: Animation scripting might greatly
benefit of that I guess. Instead of individually describing individual frames,
an animation script could set up all its objects and then just push them around
the scene as the animation progresses.

> > This is definitely something we would want - but isn't lazy evaluation
> > the domain of functions?
> >
> > Maybe we could get a consensus by allowing for named parameters in
> > functions.
>
> Yeah, I thought of blurring the distinction between functions and
> prototypes. Sometimes named parametres are useful, sometimes they are not
> needed. We could allow both, we just need a syntax for it.

How about:

MyFunction = function(positional x, y; named a, b, c) { ... }
// shorthand: function(x, y; named a, b, c) { ... }

Foo = MyFunction(2,3; b:42; a:11);


> Let's sum up the classic differences between a function and an object:
> A function has the type of its return value as soon as parametres are
> bound to it. As long as no parameters are bound to it it has a type
> determined by the number (and type) of its arguments.

So far I can follow you... I think. Note however that with a dynamically typed
language, even when parameters are bound to it, it has "the type of its return
value" no earlier than it is actually executed and the actual return value
determined.

> An object always
> has the type it was given when it was created.
> A function has parameters which are distinguished by their order. An
> object has members or properties with names.

I'd say that the parameter naming / ordering thing is rather independent of
objects vs. functions: It's just a common convention of most programming
languages that function parameters are passed by position instead of by name.


> If we add input properties which delay calculation of other properties to
> our language then functions and prototypes can perform the same task with
> a different syntax. I'm not to happy with that, _one_ way to do things
> should be enough.

I agree with that. But I guess the concept of individual properties delaying the
calculation of a whole entity would be hard to grasp for the average user, or
even for the average programmer (it is for me, at any rate ;)).


> Hm, now I'm getting a understanding of what you are aiming for. Then an
> operator meaning "apply" would also be nice, wouldn't it?
>
> perhaps
> MyTransformedSphere = MySphere ~ MyTransform;

Hm... there is something to this indeed.

However, some things need to be clarified:

Using bare expressions within a curly brace doesn't strictly create a copy, but
modifies the copy of the prototype. Would the tilde operator force creation of
a new copy?

In that case, it would be equivalent to:

MyTransformedSphere = MySphere { MyTransform };

which is just about as easy to type. It would also then raise the question
whether the following would be possible, too:

MyColoredSphere = MySphere ~ color: #<1,0,0>;

In that sense, the tilde operator would actually be the single-statement
equivalent for curly braces (which would happen to nicely fit with the shapes
of the symbols :))


> > Duh. I've just started laying out the basics of the language, and people
> > already start exploiting its details :P
> >
> Exploitation of details makes a programming language powerful ;)

So are you saying that the concept I've presented is powerful? Thanks ;)

> Unfortunately that means paying attention to details when designing a
> language is very important.

Yup. Sure thing.

> > So how would you express such an "on-the-fly assignment" then?
>
> I don't. If I want to I assign first and then reuse the assigned variable.


Hm... occasionally I do statements like:

    FooBar( This + Is(A * rand() - 0.4) / Stupid + Example );

only to find that I want to base something else on that very same random number
- or some other sub-statement, for that matter. So sometimes I'd like to be
able to write:

    FooBar( This + Is(A * rand() as MyRand - 0.4) / Stupid + Example );
    Fnord = <1,2,3> * MyRand;

This is partially a thing of "how can that rand() dare to require me to give it
a line of its own?!", partially "duh, now I have to cut and paste that
sub-expression to its own line" laziness, and partially avoiding to type one
instance of the variable name, as in:

    MyRand = rand();
    FooBar( This + Is(A * MyRand - 0.4) / Stupid + Example );
    Fnord = <1,2,3> * MyRand;

Of course there are cases where using a full-fledged assignment statement is
much cleaner. But sometimes, to me a value has the quality of no more than a
"spin-off" of some other computation. So I'd love to have a statement saying
"oh, by the way, just remember this one for later".

Or, think of debugging a large formula. With this "on-the-fly assignment", it is
a piece of cake; no need stripping it down to individual terms (and risking to
break it again as soon as you re-assemble it because you don't want 20 lines of
assignments where a two-liner would do).


> > The thing is, I don't like those interpunctuation prefixes: When you
> > start lots of statements with these, it messes up the indentation,
> > optically speaking.
> >
>
> I'm not sure what you mean with "messing up the indentation",

Think of this syntax I had pondered:

sphere {
  .center = <0,0,0>;
  .radius = 1;
  temp = rand();
  texture {
    test = temp + 1;
    .answer = 42;
  }
  .foo = bar;
}

I think this syntax would make it perfectly plain to most developers accustomed
to the "foo.bar" field/member notation that .center is a property of the
sphere, while for instance temp is not, and texture is defined in some other
scope as well.

Alas, it really "uglifies" the indentation!


> but people
> are used to such prefixes. Just think of directory structures:

No problem with the prefixes, but I want the code to have a certain "beauty" as
well - because with code, somehow beauty is almost always related to
readability (unless of course you're going for the "exotic" beauty of some
artificial languages like whitespace, c00l or such :P).


> > I'd prefer to avoid this "scene +=" - I think it's unnecessary bulk.
> > Similarly with the "texture = texture" above.
> >
> I see what you mean. So objects apply themselves to the global object
> which is the scene itself?

Yep. Well, *anything* that is a standalone expression theoretically does. But
only for some types of values the concept of "applying it to the scene" makes
sense.


> I mean for ... end. I always find using words to open and close blocks
> hard to read.

That's where indentation was invented for. (There are even languages that
actually use indentation levels to open and close blocks.)

And in a language such as this, I think there should be a clear distinction
between the "modification blocks" - which open up a new context for "applying"
things to - and control blocks.


> Then "as" creates a reference, "modify" modifies the target of a
> reference, "=" creates a copy, and what does "modify" do if the variable
> it should modify is not a reference...

No - it's not "=" that creates a copy: This is just an alternative way of
creating a reference.

The thing that causes creation of a copy is the curly-braces modifier block,
unless explicitly used with "modify":

    MySphere = sphere;

actually creates a reference to the very basic "prototype of prototypes" sphere.

And why not? There's no reason to create a copy if you're not applying any
modifications to it anyway.

To create a copy of that prototype, one would have to write:

    MySphere = sphere {};

Note that this concept also allows creating an anonymous modified object "on the
fly", as in:

    (MyIntersect,MyNormal) = trace( MySphere { translate <2,3,4> } );


> I just want to prevent SDL 4 becoming cluttered with keywords like "as"
> and "modify" when there is a way to express the same thing in a concise
> manner without them. This may seem pedantic but SDL 3 is such a mess with
> keywords. When I started writing #macros I just wanted to call a variable
> "x"... guess what happened ;)

Yeah, that's a hassle indeed.

One simple way out of this, however, is to develop a habit of always starting
your variable names with uppercase letters. (I must confess I don't have such a
habit myself ;))

Also note that the whole smash like "blob", "sphere", "triangle", "sqr" (yeah!
my personal friend in POV 3.x!) would be made available at least for local
variables if desired.

If variable names should really be deemed an issue, how about carrying over
POV-Ray 3.x convention for control keywords to start with "#"?

So we'd have:

#for i = 1 #to 21 #step 2 #do
#end

though I wouldn't consider this pretty. Or using all uppercase, which seems to
be more seldom used for variable names (possibly because it requires one more
key to be pressed):

FOR i = 1 TO 21 STEP 2 DO
  sphere { center = <i,0,0>; radius = 1; }
END

Looks a bit antiquated, but that doesn't necessarily make it a bad idea.


Post a reply to this message

From: clipka
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 14 Apr 2009 11:05:00
Message: <web.49e4a5663a7e550ef06ce2830@news.povray.org>
"MessyBlob" <nomail@nomail> wrote:
> Generally, we could go for partial OO implementation for the scene objects,
> which means that we don't carry per-instance methods, but instead just have the
> instances (with a single pointer) locate the methods for the class, along with
> the enumerated properties. The parser would be version-matched to the engine,
> which removes any opaque enumeration from the SDL source scripts.

I'd even go as far as to move the whole scene object handling into a separate
layer, with the SDL code only checking whether the object is *any* type of
scene object, and then deferring the handling to that "scene object wrapper"
layer.

That one could in turn be comprised of nothing more than a dynamic table with
objects and their respective actual types (with the core SDL implementation
handling only indices into that table; could be pointers though of course), and
a hard-coded lookup table for each type, mapping keywords to
pointers-to-members. Plus some wrap/unwrap code for some data types, if needs
be.

Thus, a statement like

    MySphere.translate(<2,3,4>)

would be resolved to (roughly):

    value = LookupName("MySphere");
    if (value->type == SCENE_OBJECT)
    {
      SceneObjectLayer->Invoke(value->handle, "translate", Vector3d(2,3,4));
    }

while SceneObjectLayer::Invoke(handle, name, param) would be implemented as
something like:

    obj = (SceneObject*)handle;
    objClass = obj->class();
    member = LookupMember(objClass, name);
    obj->member(Unwrap(param));

which would ultimately resolve to - in this case - a call to
Sphere::Translate(Vector3d v).


Post a reply to this message

From: Lukas Winter
Subject: Re: POV-Ray 4 SDL: Some concrete proposal
Date: 16 Apr 2009 06:08:32
Message: <49e703a0@news.povray.org>
Am Tue, 14 Apr 2009 10:35:11 -0400 schrieb clipka:
> 
> I think we'll want to store references: Animation scripting might
> greatly benefit of that I guess. Instead of individually describing
> individual frames, an animation script could set up all its objects and
> then just push them around the scene as the animation progresses.
> 

Right. Then frames are just modification blocks of the scene object.

> 
> How about:
> 
> MyFunction = function(positional x, y; named a, b, c) { ... } //
> shorthand: function(x, y; named a, b, c) { ... }
> 
> Foo = MyFunction(2,3; b:42; a:11);
> 

Or even:
MySphereProducingFunction = function(named pos)
{ sphere { midpoint = pos; /*...*/ } };

Any object applied to a function block would be its return value.

> 
>> Let's sum up the classic differences between a function and an object:
>> A function has the type of its return value as soon as parametres are
>> bound to it. As long as no parameters are bound to it it has a type
>> determined by the number (and type) of its arguments.
> 
> So far I can follow you... I think. Note however that with a dynamically
> typed language, even when parameters are bound to it, it has "the type
> of its return value" no earlier than it is actually executed and the
> actual return value determined.

Yes, from the syntactical point of view "func(/*...*/)" and "func" have 
different types in most languages. I don't like this, because what type 
has func(some_parameter /*but not the other*/) then? In most languages 
you have to specify all arguments or none... Seems to be a personal 
dislike, though ;)

> 
> I'd say that the parameter naming / ordering thing is rather independent
> of objects vs. functions: It's just a common convention of most
> programming languages that function parameters are passed by position
> instead of by name.
> 
Right. Perl has named parameters but how they work seems rather obscure 
to me. Just what you'd expect from Perl ;)

> 
>> If we add input properties which delay calculation of other properties
>> to our language then functions and prototypes can perform the same task
>> with a different syntax. I'm not to happy with that, _one_ way to do
>> things should be enough.
> 
> I agree with that. But I guess the concept of individual properties
> delaying the calculation of a whole entity would be hard to grasp for
> the average user, or even for the average programmer (it is for me, at
> any rate ;)).
> 
It's just the other way round: The program doesn't follow a sequence of 
instructions but has a number of goals it has to achieve. Each time a 
resource needed to achieve the current goal is missing, the program goes 
to the next. Hopefully the resource will become available later, perhaps 
as the result of another calculation.

> 
>> Hm, now I'm getting a understanding of what you are aiming for. Then an
>> operator meaning "apply" would also be nice, wouldn't it?
>>
>> perhaps
>> MyTransformedSphere = MySphere ~ MyTransform;
> 
> Hm... there is something to this indeed.
> 
> However, some things need to be clarified:
> 
> Using bare expressions within a curly brace doesn't strictly create a
> copy, but modifies the copy of the prototype. Would the tilde operator
> force creation of a new copy?
> 
> In that case, it would be equivalent to:
> 
> MyTransformedSphere = MySphere { MyTransform };
> 
> which is just about as easy to type. It would also then raise the
> question whether the following would be possible, too:
> 
> MyColoredSphere = MySphere ~ color: #<1,0,0>;
> 
> In that sense, the tilde operator would actually be the single-statement
> equivalent for curly braces (which would happen to nicely fit with the
> shapes of the symbols :))
> 

Supplying your own rules for applying a object to some other object would 
just be an act of overloading the ~ operator. Something like

PaintInHappyColors = basic {}; //clone the most fundamental prototype

operator(object ~ PaintInHappyColors)
{
  pigment { color = <rand(), rand(), rand()>; };
}

> 
>> > So how would you express such an "on-the-fly assignment" then?
>>
>> I don't. If I want to I assign first and then reuse the assigned
>> variable.
> 
> 
> Hm... occasionally I do statements like:
> 
>     FooBar( This + Is(A * rand() - 0.4) / Stupid + Example );
> 
> only to find that I want to base something else on that very same random
> number - or some other sub-statement, for that matter. So sometimes I'd
> like to be able to write:
> 
>     FooBar( This + Is(A * rand() as MyRand - 0.4) / Stupid + Example );
>     Fnord = <1,2,3> * MyRand;
> 
> This is partially a thing of "how can that rand() dare to require me to
> give it a line of its own?!", partially "duh, now I have to cut and
> paste that sub-expression to its own line" laziness, and partially
> avoiding to type one instance of the variable name, as in:
> 
>     MyRand = rand();
>     FooBar( This + Is(A * MyRand - 0.4) / Stupid + Example ); Fnord =
>     <1,2,3> * MyRand;
> 
> Of course there are cases where using a full-fledged assignment
> statement is much cleaner. But sometimes, to me a value has the quality
> of no more than a "spin-off" of some other computation. So I'd love to
> have a statement saying "oh, by the way, just remember this one for
> later".
> 
> Or, think of debugging a large formula. With this "on-the-fly
> assignment", it is a piece of cake; no need stripping it down to
> individual terms (and risking to break it again as soon as you
> re-assemble it because you don't want 20 lines of assignments where a
> two-liner would do).
> 

The C way to do that:

while((error_code = function_returning_error_code()) == 0)
{
  /*do something*/
}

Easy, because = returns the assigned variable. That does definitely 
confuse a non-programmer who doesn't know the difference between = and ==.

So your example would become

FooBar( This + Is(A * (MyRand = rand()) - 0.4) / Stupid + Example );
Fnord = <1,2,3> * MyRand;

>> I'm not sure what you mean with "messing up the indentation",
> 
> Think of this syntax I had pondered:
> 
> sphere {
>   .center = <0,0,0>;
>   .radius = 1;
>   temp = rand();
>   texture {
>     test = temp + 1;
>     .answer = 42;
>   }
>   .foo = bar;
> }
> 
> I think this syntax would make it perfectly plain to most developers
> accustomed to the "foo.bar" field/member notation that .center is a
> property of the sphere, while for instance temp is not, and texture is
> defined in some other scope as well.
> 
Would it? I never write "this->member" in C++, just member. Some people 
prefix their members with "m_", I don't. It's a matter of personal 
taste...

> Alas, it really "uglifies" the indentation!
> 
Every reference to a variable outside the current scope necessarily does 
this, if I understand you correctly.

> 
> No problem with the prefixes, but I want the code to have a certain
> "beauty" as well - because with code, somehow beauty is almost always
> related to readability (unless of course you're going for the "exotic"
> beauty of some artificial languages like whitespace, c00l or such :P).
> 

> 
>> I mean for ... end. I always find using words to open and close blocks
>> hard to read.
> 
> That's where indentation was invented for. (There are even languages
> that actually use indentation levels to open and close blocks.)
> 
> And in a language such as this, I think there should be a clear
> distinction between the "modification blocks" - which open up a new
> context for "applying" things to - and control blocks.
> 
Another matter of taste, I suppose. It's just that when I want my code to 
be verbose, then _I_ want to introduce the verbosity, not the designer of 
the programming language I happen to code in.

> 
>> Then "as" creates a reference, "modify" modifies the target of a
>> reference, "=" creates a copy, and what does "modify" do if the
>> variable it should modify is not a reference...
> 
> No - it's not "=" that creates a copy: This is just an alternative way
> of creating a reference.
> 
> The thing that causes creation of a copy is the curly-braces modifier
> block, unless explicitly used with "modify":
> 
>     MySphere = sphere;
> 
> actually creates a reference to the very basic "prototype of prototypes"
> sphere.
> 
> And why not? There's no reason to create a copy if you're not applying
> any modifications to it anyway.
> 
> To create a copy of that prototype, one would have to write:
> 
>     MySphere = sphere {};

Sounds good :)

> 
>> I just want to prevent SDL 4 becoming cluttered with keywords like "as"
>> and "modify" when there is a way to express the same thing in a concise
>> manner without them. This may seem pedantic but SDL 3 is such a mess
>> with keywords. When I started writing #macros I just wanted to call a
>> variable "x"... guess what happened ;)
> 
> Yeah, that's a hassle indeed.
> 
> One simple way out of this, however, is to develop a habit of always
> starting your variable names with uppercase letters. (I must confess I
> don't have such a habit myself ;))
> 
> Also note that the whole smash like "blob", "sphere", "triangle", "sqr"
> (yeah! my personal friend in POV 3.x!) would be made available at least
> for local variables if desired.
> 

As all objects will be prototypes I don't think any special treatment 
will be required. These prototypes could even come from special internal 
includes. Most of the time I won't need a poly and if I want to create 
one I just write

include "internal:poly"

poly
{ /*blahblah*/
};

Of course cameras and basic modifiers should be included by default. 
Namespaceing on the other hand is just too much typing for a lazy person 
like me :P

> If variable names should really be deemed an issue, how about carrying
> over POV-Ray 3.x convention for control keywords to start with "#"?
> 
> So we'd have:
> 
> #for i = 1 #to 21 #step 2 #do
> #end
> 
> though I wouldn't consider this pretty. Or using all uppercase, which
> seems to be more seldom used for variable names (possibly because it
> requires one more key to be pressed):
> 
> FOR i = 1 TO 21 STEP 2 DO
>   sphere { center = <i,0,0>; radius = 1; }
> END
> 
> Looks a bit antiquated, but that doesn't necessarily make it a bad idea.

There should really be opinion polls among POV-Ray users to decide on 
prettyness ;)


Post a reply to this message

Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.