Jump to content

SoD's Interchange File Format


SoulofDeity
 Share

Recommended Posts

Trying to find a good 3D file format has proven difficult, so I eventually just gave up and decided to work on my own.

 

 

Syntax-wise, there are only 2 rules:

  • Anything after an unquoted # symbol on a line is ignored
  • Everything is an object, following the EBNF format: `object = type , [ name ] , ( objects | values | value ) ;`, where 'name' is the quoted name of the object, 'objects' is set of objects between curly braces, 'values' is a set of values between square brackets, and 'value' is a set of one or more numbers, booleans, quoted strings, or identifiers between  between parenthesis.

 

An example of what it looks like:

# This is a comment that will be ignored.

Object "My Object"
{
  Vertices
  [
    "Morph Target 1"
    {
      Float3 "Positions"
      [
        (-0.30779600 +0.00433517 +0.00000000) (+0.29912600 +0.00433517 +0.00000000)
        (+0.29912600 +0.00433517 +0.48337000) (-0.30779600 +0.00433517 +0.48337000)
        (-0.30779600 +0.36415300 +0.48337000) (+0.29912600 +0.36415300 +0.48337000)
        (+0.29912600 +0.36415300 +0.00000000) (-0.30779600 +0.36415300 +0.00000000)
      ]
    }
  ]
  Surfaces
  [
    "Polygon Mesh 1"
    {
      Faces
      [
        (6 2 1) (2 6 5) (4 0 3) (0 4 7) (6 0 7) (0 6 1)
        (2 4 3) (4 2 5) (4 6 7) (6 4 5) (2 0 1) (0 2 3)
      ]
    }
  ]
}

This is just a ghist of it. What I'm aiming for is a text-based interchange format that supports skeletal, morph-target, texture coordinate, and texture reference animation. In the above example, you'll see that each set of vertices can have one or more morph targets and each surface can have one or more polygon meshes. The scene graph will be represented in a similar format, but a separate file.

 

 

Any suggestions are welcome

Link to comment
Share on other sites

An intermediate file format is a good idea. The conversion software should be something simple to put together if you're converting from one text-based format like obj to another.

 

Exactly. The closest thing I could find to a royalty free open interchange format was Collada, which is a nightmare (just try importing or exporting *.dae files in Blender...)

 

 

So far, the structure I've came up with is:

Vertices
  Morph Target
    Positions
    Normals
    Colors
    Weights
Surfaces
  Polygon Mesh
    Edges
    Faces
Textures
  Sampler
    Repeat Mode
    Mirror Mode
    Offset
    Tiling
    Source
      Image
      Region

Unlike most 3D model formats, each texture map gets it's data from a particular region of a texture atlas referenced by Sampler.Source.Image. Using a texture atlas allows you to have texture reference animation by animating the origin and/or size of the texture map's source. The advantages of doing this over simply animating texture coordinates is that your texture atlases don't have to be powers of two in size and that it consumes far less memory.

 

Materials are still in the planning process, but I'm thinking that each material should have a rasterizer and texturizer. The rasterizer would consist of what is mostly done by vertex shaders (transformation + lighting) with fallback modes for fixed pipelines. The texturizer would consist of what is mostly done by fragment shaders (multi-pass sampling + combining). There would be no shading language in the traditional sense, but the simplicity and separation of concern would allow you to easily convert to other shader languages (including ones with either fixed or only partially programmable pipelines like the N64).

Link to comment
Share on other sites

This is actually a separate idea, but I'm too lazy to create a topic for it...

 

Basically, I've been working on a new programming language. I want to make something that I can use on the go, so my primary goals are conservation of screen space & minimal vebosity, simplicity to type, and expressivity in spite of redundancy. My primary inspirations come from Basic, C++, Lisp, and Python.

 

The first goal was to simplify variable declaration. The first thing that came to mind was to use automatic type deduction. However, typing "var" all over the place seems like an obvious anti-pattern. So I dropped the "var" and decided that the initialization of a variable should be declaration of that variable. eg. "x = 5" would be a declaration of x if it hasn't been declared, and it's type would be "int". Then I considered re-usage. For things like enumerating through collections of objects of different types, the variable may need to change types. Granted, register allocation optimization can do this automatically, but expressing it visually helps to make code more clear. For this reason, it's be best if all variables are dynamically typed at compile time. However, you could enforce a specific type like "x as int = 5". The difference is that the following code:

x as string = "Text"
x = 5

Is equivalent to typing:

x = "Text"
x = 5 as string

In this case, all values assigned to "x" are implicitly casted to "string". The second thing I considered was declaring multiple variables at once. Consider something like, "x = 5, y = 5". There are two equals signs here. An "=" symbol is pretty annoying to type on a phone, so I decided to adopt the Python concept of tuple-assignment: "x, y = 5, 5". But then this causes a second issue, how do we assign static types now? Would it be "x as int, y as int = 5, 5"? With that, there are two "as" keywords, so instead, I decided to rearrange it:

x, y as int, int = 5, 5

Oops! Looks like I inadvertantly added product-types to my language... Having to type "int" twice though seems like such a tedious thing to do. So why not add a rule where a single element product-type can be assigned to a tuple of any size. Then we can simplify the code to:

x, y as int = 5, 5

At first glace, this may seem a bit verbose, but that's just a trick of the eyes. It's actually just as compact as C/C++ declarations, and far more compact if you use the preferred dynamically typed declarations. A side by side comparison:

// dynamically typed declaration (only dynamic at compile-time)
i, j, s = 5, 5, "Text"
x, y, z = 1, 2, 3

// statically typed declaration
i, j, s as int, int, string = 5, 5, "Text"
x, y, z as int = 1, 2, 3

// C declaration
int i = 5, j = 5; string s = "Text";
int x = 1, y = 2, z = 3;

// C++14 dynamically-typed declaration
auto i = 5, j = 5; auto s = "Text";
auto x = 1, y = 2, z = 3;

Ultimately, the only case where the C/C++ code is shorter is when you try to declare static typed variables. Even then, the difference is only about a 2 character gain for each symbol. But that loss is completely meaningless in the face of how this type of variable declaration simplifies the code you write.

 

old notes:

 

 

Rather than using the standard C-style "for" loops, I went back to the Basic's:

for i = 0 to 5 by 1    // 'do' is no longer a keyword, see edit
  something()

Compare this to the C++:

for (int i = 0; i < 5; i++)
  something()

But that's not all. Lets take a look at our for-loop again. A majority of the time, you'll increment by one in a for-loop. So, the "by 1" part is an antipattern. It should be implicit. Also, we almost always start at 0 anyhow, so "= 0" should also be implicit. Now, we have:

for i to 5            // 'do' is no longer a keyword, see edit
  something()

This is only half the size of the C++ counterpart, but now comes the final insult to injury. We have tuples.

// my language
for i, j to 5 by 2    // 'do' is no longer a keyword, see edit
  something()

// c++
for (int i = 0, j = 0; i < 5 && j < 5; i += 2, j += 2)
  something()

*rubs nipples erotically*

 

Of course, enumeration is nice as well:

// my language
for e in c            // 'do' is no longer a keyword, see edit
  something()

// c++98
using namespace std;
void f (void *e) { something(); }
for_each(begin(c), end(c), f);

// c++11
for (auto& e : c)
  something()

// c++14
for (e : c)
  something()

It may look like the c++14 version is shorter, but you actually gain 1 keystroke because the parentheses and colon require the use of the shift key.

 

One thing you may have noticed is that I'm using the keyword "do" to declare when the next indented block begins. You may want to ask, isn't that also an antipattern as it serves no purpose? Actually, it does have a purpose. Because the language uses whitespace instead of brackets to conserve screen space, continuing on a new line requires an escape character like '\'. This character is annoying as hell to type on a phone. However, if you make 2 rules like: "all if and for statements must have their conditionally executed code in a sub-block" and "all sub-blocks must begin with the 'do' keyword, then you can do this:

for i = MyNameSpace.SomeModule.ConstantStartValue to SomeStopValue
     by MyNameSpace.SomeModule.ConstantStepValue do
  something()

No need for a '\' since a 'do' must come after a 'for'. If you're using multiple iterators, those two little easily-typed letters could save you from having to switch back and forth to your symbol osk 2 or more times. You could also use the 'do' keyword to create an sub-scope for encapsulation, like you would normally do with brackets in C or C++.

EDIT: Nope, you were right to question if you did. It is an antipattern. It would make no sense at all to put  a newline after the "to" or "by" keywords unless you have some form of dyslexia that makes that look good to you, and both "to" and "by" will never appear at the beginning of a line. The "do" keyword is thus eliminated, so if-statements and for-loops are even smaller.

 

 

 

 

One newer idea I had in mind was the concept of ranges, declarable as "[ <start> to ] <stop> [ by <step> ]". eg. "0 to 5 by 1", "0 to 5", "5 by 1", and "5" are all valid ranges. Collections are enumerated as "for e in c". How ranges are iterated is now up to debate since an assignment of a range to 'i' negates how type deduction works.

 

I think we can all agree that those 2 little characters we sacrificed for static-typing are well-worth the ability to write for-loops that are about 1/2 to 1/3 the size of the ones in most other languages. Currently, I'm also considering generics. Something like "vector<int>" is ugly and tedious to type, so I though maybe "vector of int" would be nice. But then, you got to consider things like "vector<vector<int> >" being "vector of vector of int", and how you could apply such a style of generics to functions.

 

 

Another idea I had for my language is how it will manage raw memory. In C, there are no arrays. "x[5]" is merely shorthand for "*(x+5)". In my language, there will be no pointers. They simply add too much complexity to the language. Instead, I've been considering alternatives such the Basic's peek/poke approach and pinning addresses to vectors. The advantage of the first approach is that I could support multiple addressing modes through tuples. eg. "poke (0x1000, 0x7c00), 0x01234567" would write "0x01234567" to the address 1000:7c00. Granted, it could also be written "0x0017c000", but that's aside the point. Consider newer pc's where there's 16GiB of RAM, with a 48-bit data bus. That won't fit into a 32-bit integer. There are also machines that have multiple addressing modes. But, this is just an idea.

 

 

Anyhow, there's still much more work to be done as far as this language goes. I'm avoiding any specific paradigms and focusing specifically on what works in the simplest way possible; taking the least amount of time and effort.

Link to comment
Share on other sites

On third thought, 'do' is a bit more than boilerplate. Compare "for e in c something()" with "for e in c do something()". It adds to the readability of code, especially for one-liners.

 

Still pondering iteration, I think I might change the format of ranges to "[from <start>] to <stop> [by <step>]", and the format of an iterated for-loop to "for i r"; where "i" is the iterator and "r" is the range. Then, your basic constructs are:

for e in c do something()

for i from 0 to 5 by 2 do something()
for i from 0 to 5 do something()
for i to 5 by 2 do something()
for i to 5 do something()

for i, j to 5, 5 by 2, 2 do
  something()

----- The C++ Equivalents -----
for (auto& e : c) something()

for (int i = 0; i < 5; i += 2) something()
for (int i = 0; i < 5; i++) something()
for (int i = 0; i < 5; i += 2) something()
for (int i = 0; i < 5; i++) something()

for (int i = 0, j = 0; i < 5 && j < 5; i += 2, j += 2)
  something()

It's a tad lengthier than before, but still much more compact than traditional for loops.

 

 

Just some babbling about things on my mind, pay no attention...

 

 

 

 

 

Another idea I had in mind to reduce code size was to use a "with" keyword like:

x = 5
v = Vector3(0, 0, 0)
with v do
  x = 1
  y = 2
  z = 3

Here, the "with" keyword specifies that "this" is "v" so you don't have to type out "v.x = 1", "v.y = 2", and "v.z = 2". Semantically speaking, "v.x = 5" is equivalent to "with v do this.x = 5", "with v do .x = 5", or "with v do x = 5". Note that because "with" merely specifies what "this" is and "this" never overrides the current scope, the above code would actually be parsed as:

x = 5
v = Vector3(0, 0, 0)
x = 1
v.y = 2
v.z = 3

You'll probably notice I haven't mentioned "if/else" and "while/do" statements yet. I'm still putting a lot of thought into them. eg. I'm considering having "unless" and "until" keywords as counterparts to "if" and "while" in order to increase the readability of code. I'm also trying to decide if a "then" keyword is necessary, and pondering the syntax in general...

if x is 1 then
  something()
else if x is 2 then
  something()
else unless x is 3
  something()
else
  something()

if x is 1 do
  something()
else if x is 2 do
  something()
else unless x is 3 do
  something()
else do
  something()

if x is 1 then do
  something()
else if x is 2 then do
  something()
else unless x is 3 do
  something()
else do
  something()

All of these just feel unnatural, so I've been digging around to see if there might be anything more elegant. No luck so far though.

 

Another thing I've avoided talking about is functions. This is mainly because I want to have anonymous functions and non-anonymous functions have relatively similar syntax, but I'm not sure how to go about that yet. Especially when it comes to doing it in a way that doesn't use a bunch of symbols. To be honest, I'm also considering somehow doing away with parentheses for passing arguments to functions since anything separated by commas is a tuple and parentheses are annoying to type. eg. typing `printf "%s\n", "Hello World!"`. One additional plus is that it's shorter. But this introduces an issues like whether `x = x + sin theta - cos theta` should be evaluated as `x = x + sin(theta) - cos(theta)` or `x = x + sin(theta - cos(theta))`. A solution would be to have the order of operations explicitly state that functions calls have a higher precedence, and thus the second interpretation would only happen if you rewrote the code as `x = x + sin (theta - cos theta)`. Generally speaking, you'll actually end up using more parentheses this way though, so this isn't really a good approach.

 

Another interesting way of looking at it is that each function is a sub-program. In languages like bash or batch, each program acts as a filter operating on a stream of data and the options passed to the function merely give instructions on how to manipulate that stream. Now the true issue at hand is much more clear: we're multiplexing values with arguments. Syntax like 'print("test")' feels more natural because it counteracts that multiplexing by making it appear as though you're making an annotation about "print". To prove this theory, consider the following:

x = x + sin//theta// - cos//theta//
print//"%s\n", "Hello"//

No programming language uses this syntax, yet for some reason, it feels natural. Why? Because as programmers, we learned that "//" means comment or annotation, so we just ignore it. All we really 'see' is "x = x + sin - cos". So how can this knowledge be applied? One idea is to simply reword things a bit...

x = x + sin of T - cos of U
  where T, U = theta, theta

Now, this is quite a bit longer than "x = x + sin (theta) - cos (theta)", but we've gotten rid of the parentheses while keeping it just as easy to read. Don't worry, I don't plan on using this synta

x in my language, it's merely to demonstrate that alternatives exist if you know that the problem is not "how do I pass arguments to a function?", but rather, "how do I do it without drawing attention from the reader?",

 

 

 

I finally decided on a good construct for function declaration. Basically, there are no functions. There are only events, which are handled via the 'on' keyword. eg.

on print text do
    something()

As with MS visual languages, events can also have senders.

on Open path, text from File do
    something()

This will only catch events that are signalled from File's. eg. `file.Open("file.txt", "rt")`. It's a unique approach to functions compared to most other languages.

 

--------------------------

 

EDIT:

A bit more theorizing... As I stated before, I'm a bit unhappy with the syntax of traditional if-statements. While pondering this, I thought of something kind of interesting.

if (x == 5)
  then
    something()
  else
    something()

is essentially

switch (x == 5)
  case true
    something()
  case false
    something()

You're just omitting and implicity casting to what it is that you're comparing against. Instead of having if-statements, it may be a better idea to improve the syntax of switch-statements.

Link to comment
Share on other sites

I've always preferred the system of switch statements compared to if/else branches since they allow for more easily readable branches, not to mention you could still include else as a handler in the event of unexpected input.

 

switch (x)
case 2
something()
case 4
something()

case else
something()

  • Like 1
Link to comment
Share on other sites

I've always preferred the system of switch statements compared to if/else branches since they allow for more easily readable branches, not to mention you could still include else as a handler in the event of unexpected input.

 

switch (x)

case 2

something()

case 4

something()

case else

something()

 

Something I was thinking about at work today was a format like:

if x == 5
then do
    something()
else do
    something()

if x
is 1 do
    something()
is 2 do
    something()
else do
    something()

where "then" captures all non-zero/null values, "is" captures specific values, and "else" captures all remaining values. This way the general syntax of if statements is pretty much the same. The main issue though is "else if". Technically, there's no such thing... The if-statement is just a block-instruction being executed by "else". However, this illusion reduces the need to have an extra level of indentation into code. That said, I'm still not 100% comfortable with my "if _ is _ do _ else do _" format. though I think it's a bit of an improvement.

 

You have any other ideas?

Link to comment
Share on other sites

You could use braces to capture multiple values or a range:

is (2,5,7,22) do
something()
is (2-22) do
something()
 
 
is ("cats","dogs","eels","fish") do
something()

 

I'm trying to avoid parentheses and brackets as much as possible. They require use of a shift key and are difficult to type with an osk on a phone.

 

EDIT:

Also, my language does have tuples since I'm borrowing Python syntax for variable declaration; so comparison by "is" wouldn't work. Perhaps a comparison like that could reuse the "in" keyword.

Link to comment
Share on other sites

You could use braces to capture multiple values or a range:

is (2-22) do
something()

 

If you do decide to go this route, I would use "to" instead of "-" because the minus operator is likely to be used elsewhere.

 

So:

is (2 to 22) do

something()

 

Additionally, does your language ignore whitespace (hard returns, etc)? If it does not then parens arent even needed. Plus if "is" must be followed by "do" then the entire expression can be read without the need for parens.

Link to comment
Share on other sites

If you do decide to go this route, I would use "to" instead of "-" because the minus operator is likely to be used elsewhere.

 

So:

is (2 to 22) do

something()

 

Additionally, does your language ignore whitespace (hard returns, etc)? If it does not then parens arent even needed. Plus if "is" must be followed by "do" then the entire expression can be read without the need for parens.

 

We can probably just borrow the range syntax from for loops.eg. "from 2 to 22 by 1". Note that the "from <start>" and "by <step>" parts can be omitted. The language does pay attention to whitespace, since it uses indentation instead of using brackets. eg.

on main argc, argv do
    if argc > 1
    then do
        for i from 1 to argc do
            printf ("%s\n", argv [i])
            next                              # not needed, just for example
    else do
        printf ("Error: Not enough arguments.\n")

if-statements are a little verbose and feel out of place...

 

 

EDIT #1:

 

Something I was thinking about events in regards to type safety. The advantage of dynamic typing  (as seen above) is that it's much less verbose. However, it shifts the workload of type-detection off to the runtime, and thus is slower. One idea I had is something like:

on main argc, argv = 0, char[,] do
  something()

Here, instead of specifying types, we're specifying default values for the parameters. This has 2 benefits: type deduction and reducing code size by allowing you to omit parameters in some cases. The only issue is that this prevents the use of objects with constructors.

 

 

 

 

EDIT #2:

Another idea instead of static typing is default generic typing, where:

on main argc, argv do
  something()

Is equivalent to:

template <typename T, typename U, typename V>
T main (U argc, V argv) {
  something();
}

Only the code for types that are used are generated. So, if some code calls:

main (0.5, "Hello")

Then the code for:

int main (float argc, string argv);

Will be generated. Of course, we'll also want some way of generating code regardless of whether or not it's used for external linking; like how C# uses the "where" keyword. Forcing specific code to be generated will have a lengthier syntax than C or C++, but generally, code written in my language will be far more polymorphic and reusable.

 

 

EDIT #3:

 

Another idea I just had, using an 'at' keyword to create labels for loops. eg.

for i to 5 at loop1 do
    for j to 5 at loop2 do
        next loop1

This way, you can skip and break out of multiple levels of loops.

 

 

EDIT #4:

 

Another idea that just popped into my head, instead of a "break" keyword, you have "enter" and "leave" keywords. The "leave" keyword is pretty much self explanatory, but the "enter" keyword is pretty neat. Consider the following code:

i = 5
while i < 5 do
  something()

Typically, "something()" would never get executed because 'i' is >= 5. However, the enter keyword allows you to ignore the condition and jump into the block regardless. eg.

i = 5
enter while i < 5 do
  something()

Which is equivalent to the traditional:

int i = 5;
do {
  something();
} while (i < 5);

Even cooler is that because the "at" keyword allows you to label blocks of code, you can do this:

if someCondition do
  enter loop
else if someOtherCondition do
  enter loop
for i to 5 at loop do
  something ()

Here, if 'i' is < 5 or someCondition or someOtherCondition is true, then the loop will be executed. Algebraically speaking,  `if (someCondition || someOtherCondition || i < 5) enter loop`

 

 

EDIT #5:

 

Another idea, being able to label 'do' blocks. eg.

at place do
  something()

enter place

It's a sort of fake goto statement. Actually, it technically could be used as one like:

at place do leave
enter place

The above would be an infinite loop. For syntactic purposes, this could perhaps be rewritten as

leave at place
enter place

or

void at place
enter place

MV5BMjEzNzMzNzQzNl5BMl5BanBnXkFtZTcwNjEx

Link to comment
Share on other sites

Here's an unfinished presentation I've been working on that briefly summarizes my conclusions about popular concepts in programming, what I define to be a good language, and the design decisions for my language. http://www.mediafire.com/download/r68oy7qc07g4awv/Language.pptx

 

There's still a bit more to go. My deadline for this is 07/05/15 (this Monday).

Link to comment
Share on other sites

This may just be the grad school coming out of me, but you make alot of absolute statements without giving any sources or proof. Is this by design?

 

I'm not particularly good at citing things. I basically just read a lot of articles and books about these subjects from various authors, comparing theory and practice, and came to my own conclusions.

 

 

The ones that I know most people would be pissed off by are my slides on garbage collection and object-oriented programming. But they're true. Heavy use of references and pointers scattered all about leads to a lot of cache misses, mark-and sweep algorthms have considerable overhead, and in almost every OO-programming language, the use of finalizers is discouraged because some GC's may never even collect at all. GC makes use of linked lists, which by Bjarne Stroustrup goes on record for having made an entire presentation showing that they're worse than vectors in every single way (indexing, insertion, allocation, etc.) because they cannot make use of the cache. Additionally, with reference counting, there are cases in which you can accidentally create a reference without knowing it. The reference count will then be greater than 0 despite nothing actually referencing it. As a result, the object is never freed. This is the cause of many C++ memory leaks.

 

With object-oriented programming, you have to understand that by encapsulating methods in specific classes, you're placing a type-constraint. Which is counter-intuitive because it's pretty much the exact opposite of polymorphism. The only useful thing encapsulation brings to the table is data-hiding, but that's not an exclusive thing. To work around these type constraints, OOP uses inheritance. This is well known to be a horrible and flawed way of improving polymorphism. This is why many newer languages are making use of traits and mixins. OOP has no benefits at all, adds unnecessary complexity, and requires tons of boilerplate. I believe it was Linus Torvalds who had said that the only thing OOP does is allow you to write structured spagetti-code. The example I gave in my presentation shows a way in which you can actually write far less code that's much simpler while being far more polymorphic. I also made note of Alan Kay's quote that modern OOP is not what he invisioned. Which, after reading his original work where he introduced the concept, I can affirm that this is true. What he was talking about is most closely related to actor-oriented programming, though not entirely the same.

 

My assertions on what makes a good programming feature are based on my studies of linguistics. Short and simple words that express abstract ideas effectively increase how well people can communicate. What is most important in a programming language is readability.

Link to comment
Share on other sites

I could argue several of those points but it isnt going to help. Sounds like your mind is made up :)

 

I would recommend that you add a few sources because technically if you dont and you turn this in, it is plagiarism. I would hate for your effort to be seen as such :)

Link to comment
Share on other sites

I could argue several of those points but it isnt going to help. Sounds like your mind is made up :)

 

I would recommend that you add a few sources because technically if you dont and you turn this in, it is plagiarism. I would hate for your effort to be seen as such :)

 

Oh, this isn't for school. I'm meeting with someone this monday to share ideas. I scribbled a little example on a receipt, and the guy was genuinely interested in it. (I mean, he literally just sat there quitely for about 5 minutes, deep in thought at first, and while we were talking about it, he kept asking to make sure he heard me right when I said this was a statically-typed compiled language). He also happens to be a fan of object-oriented programming, so I wanted to show him exactly why I avoided it.

Link to comment
Share on other sites

OH! I misunderstood. My bad :)

 

I do like your ideas but some of it seems to be opinion more than factual base.

 

For instance, you mentioned:

The only useful thing encapsulation brings to the table is data-hiding, but that's not an exclusive thing

 

I am not entirely sure that is accurate. Encapsulation allows for a high level of abstraction in a public interface and of course it allows for strong coupling. Keep in mind I am speaking from a complex systems point of view because that is my background. Smaller systems may not have the same requirements so perhaps it is less important...?

Link to comment
Share on other sites

OH! I misunderstood. My bad :)

 

I do like your ideas but some of it seems to be opinion more than factual base.

 

For instance, you mentioned:

The only useful thing encapsulation brings to the table is data-hiding, but that's not an exclusive thing

 

I am not entirely sure that is accurate. Encapsulation allows for a high level of abstraction in a public interface and of course it allows for strong coupling. Keep in mind I am speaking from a complex systems point of view because that is my background. Smaller systems may not have the same requirements so perhaps it is less important...?

 

The high level of abstraction in the public interface while keeping other things private is what I refer to as data-hiding. Strong coupling is a very bad thing because it makes it difficult to change and reuse code as well as vastly decreasing both modularity and polymorphism.

Link to comment
Share on other sites

That may be true but isn't necessarily true. I am referring to highly modularized code. Tight coupling doesnt mean that the module can't be reused, it just means the interaction between them is heavily utilized.

 

For example a vehicle class can make boats, cars, trucks, planes, etc. Some will be more tightly coupled than others (like cars would have more characteristics that we think of for a vehicle) but it doesn't mean that it's a bad thing as it can be used (and reused) by a plethora of organizations and applications (domain allowing).

 

Large systems with a small number of modules are absolutely a bad idea to have tightly coupled (this is a bad idea in general lol). But I see your point :)

Link to comment
Share on other sites

That may be true but isn't necessarily true. I am referring to highly modularized code. Tight coupling doesnt mean that the module can't be reused, it just means the interaction between them is heavily utilized.

 

For example a vehicle class can make boats, cars, trucks, planes, etc. Some will be more tightly coupled than others (like cars would have more characteristics that we think of for a vehicle) but it doesn't mean that it's a bad thing as it can be used (and reused) by a plethora of organizations and applications (domain allowing).

 

Large systems with a small number of modules are absolutely a bad idea to have tightly coupled (this is a bad idea in general lol). But I see your point :)

 

The problem I'm talking about is when you try to replace a module. With OOP, you can't just swap out a class. Tight coupling dictates you either rewrite a majority of it for use in your code base or merge it's entire dependency web into your project. Especially in large projects, tiny changes cause huge code ripples. Generally, you should always strive for low coupling and high cohesion; so OOP by design teaches bad programming habits.

 

 

On a side note, I decided on how type constraints will work:

on add a, b for int, int or float, float do
  reply a + b

Note that these are optional unless you want to forcefully generate code for specific type signatures.

Link to comment
Share on other sites

  • 3 weeks later...

Back On Topic Now...

 

I went back to the drawing board for my interchange format.

 

What I needed was a way of representing both metadata and data. So I chose the easiest thing: '[ ]' = metadata, '{ }' = data. If the text inside of these brackets has unescaped brackets, then it's a subproperty. If not, then it's a value. For example:

File [ Name { My File.txt } Type { Text } ]
{
  Text
  {
    This is a text file! ~Awesomeness!\n
    \tLeading and trailing whitespace is ignored, so you have to manually add newlines
    and indentation.\n
    Also, properties begin with \[ \] and \{ \} so those must be escaped in text.
  }
}

Here, 'File' is an object that has the values 'Name' and 'Type' for metadata and the value 'Text' for it's data.

Link to comment
Share on other sites

 Share

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.